1
0
Эх сурвалжийг харах

Test chromatic (#269)

* test(chromatic): init and fix some story bugs

* test(workflow): add github yml

* chore(story): update storybook demo to v6

* docs(readme): add chromatic
走鹃 3 жил өмнө
parent
commit
6995204ce4
100 өөрчлөгдсөн 21078 нэмэгдсэн , 17916 устгасан
  1. 46 0
      .github/workflows/chromatic.yml
  2. 10 1
      README-zh_CN.md
  3. 10 1
      README.md
  4. 1 0
      package.json
  5. 1 1
      packages/semi-ui/_base/_story/index.scss
  6. 107 94
      packages/semi-ui/_base/_story/index.stories.js
  7. 10 11
      packages/semi-ui/_portal/_story/portal.stories.js
  8. 2 2
      packages/semi-ui/_test_/utils/table/index.js
  9. 244 221
      packages/semi-ui/anchor/_story/anchor.stories.js
  10. 306 305
      packages/semi-ui/autoComplete/_story/autoComplete.stories.js
  11. 173 152
      packages/semi-ui/avatar/_story/avatar.stories.js
  12. 30 30
      packages/semi-ui/backtop/_story/backtop.stories.js
  13. 81 85
      packages/semi-ui/badge/_story/badge.stories.js
  14. 34 37
      packages/semi-ui/banner/_story/banner.stories.js
  15. 306 272
      packages/semi-ui/breadcrumb/_story/breadcrumb.stories.js
  16. 265 239
      packages/semi-ui/button/_story/button.stories.js
  17. 345 343
      packages/semi-ui/calendar/_story/calendar.stories.js
  18. 514 498
      packages/semi-ui/card/_story/card.stories.js
  19. 4 0
      packages/semi-ui/cascader/_story/CustomTrigger/index.jsx
  20. 557 535
      packages/semi-ui/cascader/_story/cascader.stories.js
  21. 899 764
      packages/semi-ui/checkbox/_story/checkbox.stories.js
  22. 121 116
      packages/semi-ui/collapse/_story/accordion.stories.js
  23. 524 510
      packages/semi-ui/collapsible/_story/collapsible.stories.js
  24. 23 9
      packages/semi-ui/configProvider/_story/configProvider.stories.js
  25. 4 0
      packages/semi-ui/datePicker/_story/BetterRangePicker/index.jsx
  26. 4 0
      packages/semi-ui/datePicker/_story/CustomTrigger/index.jsx
  27. 83 0
      packages/semi-ui/datePicker/_story/DatePickerSlot/index.jsx
  28. 223 164
      packages/semi-ui/datePicker/_story/datePicker.stories.js
  29. 46 45
      packages/semi-ui/descriptions/_story/descriptions.stories.js
  30. 300 304
      packages/semi-ui/dropdown/_story/dropdown.stories.js
  31. 44 40
      packages/semi-ui/empty/_story/empty.stories.js
  32. 442 188
      packages/semi-ui/form/_story/form.stories.js
  33. 283 223
      packages/semi-ui/grid/_story/grid.stories.js
  34. 56 47
      packages/semi-ui/icons/_story/icon.stories.js
  35. 677 507
      packages/semi-ui/input/_story/input.stories.js
  36. 625 539
      packages/semi-ui/inputNumber/_story/inputNumber.stories.js
  37. 265 239
      packages/semi-ui/layout/_story/layout.stories.js
  38. 827 699
      packages/semi-ui/list/_story/list.stories.js
  39. 188 150
      packages/semi-ui/locale/_story/locale.stories.js
  40. 1 1
      packages/semi-ui/modal/_story/CollapsibleInModal/index.jsx
  41. 201 152
      packages/semi-ui/modal/_story/modal.stories.js
  42. 286 218
      packages/semi-ui/navigation/_story/navigation.stories.js
  43. 195 162
      packages/semi-ui/notification/_story/notification.stories.js
  44. 313 254
      packages/semi-ui/overflowList/_story/overflowList.stories.js
  45. 124 107
      packages/semi-ui/pagination/_story/pagination.stories.js
  46. 112 79
      packages/semi-ui/popconfirm/_story/popconfirm.stories.js
  47. 523 456
      packages/semi-ui/popover/_story/popover.stories.js
  48. 68 47
      packages/semi-ui/progress/_story/progress.stories.js
  49. 812 634
      packages/semi-ui/radio/_story/radio.stories.js
  50. 83 69
      packages/semi-ui/rating/_story/rating.stories.js
  51. 20 9
      packages/semi-ui/scrollList/_story/scrolllist.stories.js
  52. 2620 2418
      packages/semi-ui/select/_story/select.stories.js
  53. 336 311
      packages/semi-ui/sideSheet/_story/sideSheet.stories.js
  54. 67 58
      packages/semi-ui/skeleton/_story/skeleton.stories.js
  55. 365 246
      packages/semi-ui/slider/_story/slider.stories.js
  56. 242 214
      packages/semi-ui/space/_story/space.stories.js
  57. 76 52
      packages/semi-ui/spin/_story/spin.stories.js
  58. 258 214
      packages/semi-ui/steps/_story/steps.stories.js
  59. 144 108
      packages/semi-ui/switch/_story/switch.stories.js
  60. 1 1
      packages/semi-ui/table/_story/BetterScrollbar.tsx
  61. 1 1
      packages/semi-ui/table/_story/CustomComponents/index.js
  62. 1 1
      packages/semi-ui/table/_story/CustomFilterDropdownItem/index.jsx
  63. 1 1
      packages/semi-ui/table/_story/DynamicTable/index.jsx
  64. 1 1
      packages/semi-ui/table/_story/EventTable/index.jsx
  65. 1 1
      packages/semi-ui/table/_story/ExpandAllRows/index.jsx
  66. 1 1
      packages/semi-ui/table/_story/FixAllColumnsWithoutWidth.tsx
  67. 1 1
      packages/semi-ui/table/_story/FixedExpandedRows/index.js
  68. 1 1
      packages/semi-ui/table/_story/FixedTable/index.js
  69. 1 1
      packages/semi-ui/table/_story/FullRender/index.jsx
  70. 1 1
      packages/semi-ui/table/_story/GroupedColsFixed/index.jsx
  71. 1 1
      packages/semi-ui/table/_story/GroupedColsFixedJSX/index.jsx
  72. 1 1
      packages/semi-ui/table/_story/GroupedColsFixedVirtualized/index.jsx
  73. 1 1
      packages/semi-ui/table/_story/GroupedColsFixedVirtualizedGroups/index.jsx
  74. 1 1
      packages/semi-ui/table/_story/InSideSheet/index.jsx
  75. 1 1
      packages/semi-ui/table/_story/InfiniteScroll/index.js
  76. 1 1
      packages/semi-ui/table/_story/JSXColumnsComplex.jsx
  77. 1 1
      packages/semi-ui/table/_story/JSXColumnsNest.tsx
  78. 1 1
      packages/semi-ui/table/_story/JSXTitles/index.js
  79. 4 0
      packages/semi-ui/table/_story/MassiveColumns/index.jsx
  80. 1 1
      packages/semi-ui/table/_story/ModalTable/index.jsx
  81. 4 0
      packages/semi-ui/table/_story/RTL/AlignScrollBar.jsx
  82. 1 1
      packages/semi-ui/table/_story/ResizableTable/index.jsx
  83. 1 1
      packages/semi-ui/table/_story/SelectedRows/index.js
  84. 1 1
      packages/semi-ui/table/_story/TabsTable/index.jsx
  85. 1 1
      packages/semi-ui/table/_story/VirtualTableOnCell/index.jsx
  86. 4 0
      packages/semi-ui/table/_story/VirtualizedDynamicData/index.jsx
  87. 1 1
      packages/semi-ui/table/_story/VirtualizedNotFixed/index.js
  88. 1 1
      packages/semi-ui/table/_story/WithSideSheet/index.js
  89. 511 353
      packages/semi-ui/table/_story/table.stories.js
  90. 1 1
      packages/semi-ui/table/_story/table.stories.tsx
  91. 1 1
      packages/semi-ui/table/_story/virtualized/index.js
  92. 730 653
      packages/semi-ui/tabs/_story/tabs.stories.js
  93. 214 150
      packages/semi-ui/tag/_story/tag.stories.js
  94. 391 320
      packages/semi-ui/tagInput/_story/tagInput.stories.js
  95. 226 165
      packages/semi-ui/timePicker/_story/timepicker.stories.js
  96. 159 132
      packages/semi-ui/timeline/_story/timeline.stories.js
  97. 81 70
      packages/semi-ui/toast/_story/toast.stories.js
  98. 579 481
      packages/semi-ui/tooltip/_story/tooltip.stories.js
  99. 667 584
      packages/semi-ui/transfer/_story/transfer.stories.js
  100. 1954 1800
      packages/semi-ui/tree/_story/tree.stories.js

+ 46 - 0
.github/workflows/chromatic.yml

@@ -0,0 +1,46 @@
+# .github/workflows/chromatic.yml
+
+# Workflow name
+name: 'test:chromatic'
+
+# Event for the workflow
+on:
+  pull_request:
+    branches: [ main, release, test-chromatic ]
+    paths:
+      - 'packages/**/*.scss'
+      - '!packages/**/_story/**'
+      - '!packages/**/__test__/**'
+      - '!packages/**/*.stories.[tj]sx?'
+      - '!packages/**/*.story.[tj]sx?'
+      - '!packages/**/*.test.[tj]sx?'
+      - '!packages/**/*.md'
+  push:
+    branches: [ test-chromatic ]
+    paths:
+      - 'packages/**/*.scss'
+      - '!packages/**/*.md'
+
+# List of jobs
+jobs:
+  chromatic-deployment:
+    # Operating System
+    runs-on: ubuntu-latest
+    # Job steps
+    steps:
+      - uses: actions/checkout@v1
+      - uses: actions/setup-node@v2
+        with:
+          node-version: '14'
+      - name: Install dependencies
+        run: npx lerna bootstrap
+      - name: Pre-build libs
+        run: npx lerna run build:lib
+      - name: Publish to Chromatic
+        uses: chromaui/action@v1
+        # Chromatic GitHub Action options
+        with:
+          token: ${{ secrets.GITHUB_TOKEN }}
+          # 👇 Chromatic projectToken, refer to the manage page to obtain it.
+          projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
+          buildScriptName: 'build-storybook'

+ 10 - 1
README-zh_CN.md

@@ -9,7 +9,8 @@
     
 <div align="center">
 
-[![NPM][npm-badge]][npm-url] [![FIGMA][figma-badge]][figma-url] [![LICENSE][license-badge]][license-url] [![CODECOV][codecov-badge]][codecov-url]
+[![NPM][npm-badge]][npm-url] [![FIGMA][figma-badge]][figma-url] [![LICENSE][license-badge]][license-url] 
+[![CODECOV][codecov-badge]][codecov-url] [![Chromatic][chromatic-badge]][chromatic-url]
 
 
 [npm-badge]: https://img.shields.io/npm/v/@douyinfe/semi-ui.svg
@@ -21,6 +22,8 @@
 [license-url]: https://github.com/DouyinFE/semi-design/blob/main/LICENSE
 [codecov-badge]: https://img.shields.io/codecov/c/gh/DouyinFE/semi-design
 [codecov-url]: https://app.codecov.io/gh/DouyinFE/semi-design
+[chromatic-badge]: https://img.shields.io/badge/test-chromatic-f52
+[chromatic-url]: https://www.chromatic.com/
 
 </div>
 
@@ -106,6 +109,12 @@ Semi UI 支持所有主流浏览器。
 
 加入[用户群](https://bytedance.feishu.cn/docs/doccnw93Dujm3UCkHRDTMTm1qwe#).
 
+# 💖 Thanks
+
+<a href="https://www.chromatic.com/"><img src="https://user-images.githubusercontent.com/321738/84662277-e3db4f80-af1b-11ea-88f5-91d67a5e59f6.png" width="153" height="30" alt="Chromatic" /></a>
+
+感谢 [Chromatic](https://www.chromatic.com/) 提供可视化测试平台,帮助我们审查 UI 更改和提供视觉回归测试。
+
 # 🎈 协议
 
 Semi UI 使用 [MIT 协议](LICENSE)

+ 10 - 1
README.md

@@ -9,7 +9,8 @@
     
 <div align="center">
 
-[![NPM][npm-badge]][npm-url] [![FIGMA][figma-badge]][figma-url] [![LICENSE][license-badge]][license-url] [![CODECOV][codecov-badge]][codecov-url]
+[![NPM][npm-badge]][npm-url] [![FIGMA][figma-badge]][figma-url] [![LICENSE][license-badge]][license-url]
+[![CODECOV][codecov-badge]][codecov-url] [![Chromatic][chromatic-badge]][chromatic-url]
 
 
 [npm-badge]: https://img.shields.io/npm/v/@douyinfe/semi-ui.svg
@@ -21,6 +22,8 @@
 [license-url]: https://github.com/DouyinFE/semi-design/blob/main/LICENSE
 [codecov-badge]: https://img.shields.io/codecov/c/gh/DouyinFE/semi-design
 [codecov-url]: https://app.codecov.io/gh/DouyinFE/semi-design
+[chromatic-badge]: https://img.shields.io/badge/test-chromatic-f52
+[chromatic-url]: https://www.chromatic.com/
 
 </div>
 
@@ -104,6 +107,12 @@ See [CONTRIBUTING](CONTRIBUTING-en-US.md) documentation.
 
 Join [User Group](https://bytedance.feishu.cn/docs/doccnw93Dujm3UCkHRDTMTm1qwe#).
 
+# 💖 Thanks
+
+<a href="https://www.chromatic.com/"><img src="https://user-images.githubusercontent.com/321738/84662277-e3db4f80-af1b-11ea-88f5-91d67a5e59f6.png" width="153" height="30" alt="Chromatic" /></a>
+
+Thanks to [Chromatic](https://www.chromatic.com/) for providing the visual testing platform that helps us review UI changes and catch visual regressions.
+
 # 🎈 License
 
 Semi UI is [MIT Licensed](LICENSE)

+ 1 - 0
package.json

@@ -136,6 +136,7 @@
     "babel-plugin-transform-require-context": "^0.1.1",
     "babel-runtime": "^6.26.0",
     "case-sensitive-paths-webpack-plugin": "^2.4.0",
+    "chromatic": "^6.0.6",
     "crypto": "^1.0.1",
     "css-loader": "^3.6.0",
     "enzyme": "^3.11.0",

+ 1 - 1
packages/semi-ui/_base/_story/index.scss

@@ -11,4 +11,4 @@ body {
     #root {
         padding: 20px;
     }
-}
+}

+ 107 - 94
packages/semi-ui/_base/_story/index.stories.js

@@ -1,105 +1,118 @@
 import React, { useMemo } from 'react';
-import { storiesOf } from '@storybook/react';
 import { Button, Typography, Card, Tooltip, Tag, Avatar, Rating, Nav, Layout } from '../../index';
 import { IconHelpCircle, IconUser, IconStar, IconSetting } from '@douyinfe/semi-icons';
 import './index.scss';
 
-const stories = storiesOf('All', module);
+export default {
+  title: 'Base',
+};
 
-stories.add('test always dark/light', () => {
-    function Demo() {
-        const { Text } = Typography;
-        const { Header, Footer, Sider, Content } = Layout;
+export {
+  TestAlwaysDarkLight
+};
 
-        const switchMode = () => {
-            const body = document.body;
-            if (body.hasAttribute('theme-mode')) {
-                body.removeAttribute('theme-mode');
-                // 通知官网更新当前模式,下同
-                // window.setMode("light");
-            } else {
-                body.setAttribute('theme-mode', 'dark');
-                // window.setMode("dark");
-            }
-        };
-        const opts = {
-            content: 'Hi, Bytedance dance dance',
-            duration: 3,
-        };
+const TestAlwaysDarkLight = () => {
+  function Demo() {
+    const { Text } = Typography;
+    const { Header, Footer, Sider, Content } = Layout;
 
-        const blocks = title => (
-            <Layout>
-                <Header style={{ height: 60 }}>Header</Header>
-                <Layout style={{ height: 'calc(100vh - 260px)' }}>
-                    <Sider style={{ background: 'var(--semi-color-white)' }}>
-                        <div class="semi-always-light">
-                            <Nav
-                                style={{ background: 'var(--semi-color-white)' }}
-                                // bodyStyle={{ height: '100%' }}
-                                items={[
-                                    { itemKey: 'user', text: '用户管理', icon: <IconUser /> },
-                                    { itemKey: 'union', text: '公会中心', icon: <IconStar /> },
-                                    {
-                                        text: '任务平台',
-                                        icon: <IconSetting />,
-                                        itemKey: 'job',
-                                        items: ['任务管理', '用户任务查询'],
-                                    },
-                                ]}
-                                onSelect={data => console.log('trigger onSelect: ', data)}
-                                onClick={data => console.log('trigger onClick: ', data)}
-                            />
-                        </div>
-                    </Sider>
-                    <Content>
-                      <Card
-                          title={`Semi Design ${title}`}
-                          style={{ maxWidth: 360, marginRight: 12 }}
-                          headerExtraContent={<Text link>更多</Text>}
-                      >
-                          Semi Design 是由互娱社区前端团队与 UED
-                          团队共同设计开发并维护的设计系统。设计系统包含设计语言以及一整套可复用的前端组件,帮助设计师与开发者更容易地打造高质量的、用户体验一致的、符合设计规范的
-                          Web 应用。
-                          <Tooltip content={'hi bytedance'}>
-                              <IconHelpCircle />
-                          </Tooltip>
-                      </Card>
-                      <div>
-                          <div>
-                              <Avatar style={{ margin: 4 }}>AS</Avatar>
-                              <Avatar color="red" style={{ margin: 4 }}>
-                                  BM
-                              </Avatar>
-                              <Avatar color="light-blue" style={{ margin: 4 }}>
-                                  TJ
-                              </Avatar>
-                              <Avatar style={{ color: '#f56a00', backgroundColor: '#fde3cf', margin: 4 }}>
-                                  ZL
-                              </Avatar>
-                              <Avatar style={{ backgroundColor: '#87d068', margin: 4 }}>YZ</Avatar>
-                          </div>
-                          <Tag> default tag </Tag>
-                          <Rating defaultValue={5} />
-                      </div>
-                    </Content>
-                </Layout>
-                <Footer style={{ height: 200, background: 'var(--semi-color-black)', color: 'var(--semi-color-white)' }}>Footer</Footer>
-            </Layout>
-        );
+    const switchMode = () => {
+      const body = document.body;
+      if (body.hasAttribute('theme-mode')) {
+        body.removeAttribute('theme-mode');
+        // 通知官网更新当前模式,下同
+        // window.setMode("light");
+      } else {
+        body.setAttribute('theme-mode', 'dark');
+        // window.setMode("dark");
+      }
+    };
+    const opts = {
+      content: 'Hi, Bytedance dance dance',
+      duration: 3,
+    };
 
-        return (
-            <div className="container">
-                <div>
-                    <Button onClick={switchMode}>Switch Mode</Button>
-                </div>
-                <div>
-                    <div>{blocks('default')}</div>
-                    {/* <div id="semi-always-dark">{blocks('always dark')}</div>
-                    <div id="semi-always-light">{blocks('always light')}</div> */}
-                </div>
+    const blocks = title => (
+      <Layout>
+        <Header style={{ height: 60 }}>Header</Header>
+        <Layout style={{ height: 'calc(100vh - 260px)' }}>
+          <Sider style={{ background: 'var(--semi-color-white)' }}>
+            <div class="semi-always-light">
+              <Nav
+                style={{ background: 'var(--semi-color-white)' }}
+                // bodyStyle={{ height: '100%' }}
+                items={[
+                  { itemKey: 'user', text: '用户管理', icon: <IconUser /> },
+                  { itemKey: 'union', text: '公会中心', icon: <IconStar /> },
+                  {
+                    text: '任务平台',
+                    icon: <IconSetting />,
+                    itemKey: 'job',
+                    items: ['任务管理', '用户任务查询'],
+                  },
+                ]}
+                onSelect={data => console.log('trigger onSelect: ', data)}
+                onClick={data => console.log('trigger onClick: ', data)}
+              />
+            </div>
+          </Sider>
+          <Content>
+            <Card
+              title={`Semi Design ${title}`}
+              style={{ maxWidth: 360, marginRight: 12 }}
+              headerExtraContent={<Text link>更多</Text>}
+            >
+              Semi Design 是由互娱社区前端团队与 UED
+              团队共同设计开发并维护的设计系统。设计系统包含设计语言以及一整套可复用的前端组件,帮助设计师与开发者更容易地打造高质量的、用户体验一致的、符合设计规范的
+              Web 应用。
+              <Tooltip content={'hi bytedance'}>
+                <IconHelpCircle />
+              </Tooltip>
+            </Card>
+            <div>
+              <div>
+                <Avatar style={{ margin: 4 }}>AS</Avatar>
+                <Avatar color="red" style={{ margin: 4 }}>
+                  BM
+                </Avatar>
+                <Avatar color="light-blue" style={{ margin: 4 }}>
+                  TJ
+                </Avatar>
+                <Avatar style={{ color: '#f56a00', backgroundColor: '#fde3cf', margin: 4 }}>
+                  ZL
+                </Avatar>
+                <Avatar style={{ backgroundColor: '#87d068', margin: 4 }}>YZ</Avatar>
+              </div>
+              <Tag> default tag </Tag>
+              <Rating defaultValue={5} />
             </div>
-        );
-    }
+          </Content>
+        </Layout>
+        <Footer
+          style={{
+            height: 200,
+            background: 'var(--semi-color-black)',
+            color: 'var(--semi-color-white)',
+          }}
+        >
+          Footer
+        </Footer>
+      </Layout>
+    );
+
+    return (
+      <div className="container">
+        <div>
+          <Button onClick={switchMode}>Switch Mode</Button>
+        </div>
+        <div>
+          <div>{blocks('default')}</div>
+          {/* <div id="semi-always-dark">{blocks('always dark')}</div>
+                    <div id="semi-always-light">{blocks('always light')}</div> */}
+        </div>
+      </div>
+    );
+  }
 
-    return <Demo />;
-});
+  return <Demo />;
+};

+ 10 - 11
packages/semi-ui/_portal/_story/portal.stories.js

@@ -1,18 +1,17 @@
 import React from 'react';
-import { storiesOf } from '@storybook/react';
-// import { withKnobs, text, boolean } from '@storybook/addon-knobs';
-import withPropsCombinations from 'react-storybook-addon-props-combinations';
 
 import Portal from '../index';
 
-const stories = storiesOf('Portal', module);
+export default {
+  title: 'Portal',
+}
 
-// stories.addDecorator(withKnobs);;
+export {
+  Basic
+}
 
-stories.add('Portal', () => (
-    <div>
-        <Portal>
-            123
-        </Portal>
+const Basic = () => (
+  <div>
+    <Portal>123</Portal>
   </div>
-));
+);

+ 2 - 2
packages/semi-ui/_test_/utils/table/index.js

@@ -11,7 +11,7 @@ function getRandomNumber(end = 100, start = 0) {
 function getData(total = 25) {
     const _data = [];
     for (let i = 0; i < total; i++) {
-        let age = 40 + (Math.random() > 0.5 ? 1 : -1) * Math.ceil(i / 3);
+        let age = (i * 1000) % 149;
         let name = `Edward King ${i}`;
         _data.push({
             key: String(i),
@@ -171,7 +171,7 @@ function getNestColumns() {
 function getNestData(total = 25) {
     const data = [];
     for (let i = 0; i < total; i++) {
-        let age = 40 + (Math.random() > 0.5 ? 1 : -1) * (i % 9);
+        let age = (i * 1000) % 149;
         let name = `Edward King ${i}`;
         data.push({
             key: String(i),

+ 244 - 221
packages/semi-ui/anchor/_story/anchor.stories.js

@@ -1,243 +1,266 @@
 import React from 'react';
 import { Anchor } from '../../index';
-import { storiesOf } from '@storybook/react';
 
-const stories = storiesOf('Anchor', module);
+export default {
+  title: 'Anchor',
+}
 
 const getContainer = () => {
-    const node = document.getElementById('box');
-    return node;
+  const node = document.getElementById('box');
+  return node;
 };
 
 const Link = Anchor.Link;
 
-stories.add('不同大小', () => (
-    <div>
-        <div>小号尺寸</div>
-        <Anchor size={'small'}>
-            <Link href="#welcome" title="welcome" />
-            <Link href="#api" title="api too much to show" />
-            <Link href="#contact" title="contact" />
-        </Anchor>
-        <br />
-        <div>默认</div>
-        <Anchor>
-            <Link href="#welcome" title="welcome" />
-            <Link href="#api" title="api too much to show" />
-            <Link href="#contact" title="contact" />
-        </Anchor>
-    </div>
-));
+export const Size = () => (
+  <div>
+    <div>小号尺寸</div>
+    <Anchor size={'small'}>
+      <Link href="#welcome" title="welcome" />
+      <Link href="#api" title="api too much to show" />
+      <Link href="#contact" title="contact" />
+    </Anchor>
+    <br />
+    <div>默认</div>
+    <Anchor>
+      <Link href="#welcome" title="welcome" />
+      <Link href="#api" title="api too much to show" />
+      <Link href="#contact" title="contact" />
+    </Anchor>
+  </div>
+);
 
-stories.add('不同主题', () => (
-    <div>
-        <div>点击锚点查看效果</div>
-        <br />
-        <Anchor railTheme={'primary'}>
-            <Link href="#组件" title="组件" />
-            <Link href="#设计语言" title="设计语言" />
-            <Link href="#物料平台" title="物料平台" />
-            <Link href="#主题商店" title="主题商店" />
-        </Anchor>
-        <br />
-        <Anchor railTheme={'tertiary'}>
-            <Link href="#组件" title="组件" />
-            <Link href="#设计语言" title="设计语言" />
-            <Link href="#物料平台" title="物料平台" />
-            <Link href="#主题商店" title="主题商店" />
-        </Anchor>
-        <br />
-        <Anchor railTheme={'muted'}>
-            <Link href="#组件" title="组件" />
-            <Link href="#设计语言" title="设计语言" />
-            <Link href="#物料平台" title="物料平台" />
-            <Link href="#主题商店" title="主题商店" />
-        </Anchor>
-    </div>
-));
+export const Theme = () => (
+  <div>
+    <div>点击锚点查看效果</div>
+    <br />
+    <Anchor railTheme={'primary'}>
+      <Link href="#组件" title="组件" />
+      <Link href="#设计语言" title="设计语言" />
+      <Link href="#物料平台" title="物料平台" />
+      <Link href="#主题商店" title="主题商店" />
+    </Anchor>
+    <br />
+    <Anchor railTheme={'tertiary'}>
+      <Link href="#组件" title="组件" />
+      <Link href="#设计语言" title="设计语言" />
+      <Link href="#物料平台" title="物料平台" />
+      <Link href="#主题商店" title="主题商店" />
+    </Anchor>
+    <br />
+    <Anchor railTheme={'muted'}>
+      <Link href="#组件" title="组件" />
+      <Link href="#设计语言" title="设计语言" />
+      <Link href="#物料平台" title="物料平台" />
+      <Link href="#主题商店" title="主题商店" />
+    </Anchor>
+  </div>
+);
 
-stories.add('动态展示', () => (
-    <div>
-        <div>Anchor 设置 autoCollapse 可以动态展示下一级锚点。</div>
-        <br />
-        <div>点击 1.Semi Design 查看效果</div>
-        <Anchor autoCollapse={true}>
-            <Link href="#Semi Design" title="1. Semi Design">
-                <Link href="#组件" title="1.1 组件">
-                    <Link href="#头像" title="1.1.1 Avatar" />
-                    <Link href="#按钮" title="1.1.2 Button" />
-                    <Link href="#图标" title="1.1.3 Icon" />
-                </Link>
-                <Link href="#物料" title="1.2 物料" />
-                <Link href="#主题商店" title="1.3 主题商店" />
-            </Link>
-            <Link href="#设计语言" title="2. 设计语言" />
-        </Anchor>
-        <br />
-        <div>默认不进行动态折叠</div>
-        <Anchor autoCollapse={false}>
-            <Link href="#Semi Design" title="1. Semi Design">
-                <Link href="#组件" title="1.1 组件">
-                    <Link href="#头像" title="1.1.1 Avatar" />
-                    <Link href="#按钮" title="1.1.2 Button" />
-                    <Link href="#图标" title="1.1.3 Icon" />
-                </Link>
-                <Link href="#物料" title="1.2 物料" />
-                <Link href="#主题商店" title="1.3 主题商店" />
-            </Link>
-            <Link href="#设计语言" title="2. 设计语言" />
-        </Anchor>
-    </div>
-));
+export const autoCollapse = () => (
+  <div>
+    <div>Anchor 设置 autoCollapse 可以动态展示下一级锚点。</div>
+    <br />
+    <div>点击 1.Semi Design 查看效果</div>
+    <Anchor autoCollapse={true}>
+      <Link href="#Semi Design" title="1. Semi Design">
+        <Link href="#组件" title="1.1 组件">
+          <Link href="#头像" title="1.1.1 Avatar" />
+          <Link href="#按钮" title="1.1.2 Button" />
+          <Link href="#图标" title="1.1.3 Icon" />
+        </Link>
+        <Link href="#物料" title="1.2 物料" />
+        <Link href="#主题商店" title="1.3 主题商店" />
+      </Link>
+      <Link href="#设计语言" title="2. 设计语言" />
+    </Anchor>
+    <br />
+    <div>默认不进行动态折叠</div>
+    <Anchor autoCollapse={false}>
+      <Link href="#Semi Design" title="1. Semi Design">
+        <Link href="#组件" title="1.1 组件">
+          <Link href="#头像" title="1.1.1 Avatar" />
+          <Link href="#按钮" title="1.1.2 Button" />
+          <Link href="#图标" title="1.1.3 Icon" />
+        </Link>
+        <Link href="#物料" title="1.2 物料" />
+        <Link href="#主题商店" title="1.3 主题商店" />
+      </Link>
+      <Link href="#设计语言" title="2. 设计语言" />
+    </Anchor>
+  </div>
+);
 
-stories.add('工具提示', () => (
-    <div>
-        <div>工具提示可以在 Link 超出最大宽度时显示 Link 的文字内容</div>
-        <br />
-        <Anchor showTooltip={true}>
-            <Link href="#组件" title="组件" />
-            <Link href="#设计语言" title="设计语言" />
-            <Link href="#物料平台" title="物料平台" />
-            <Link href="#主题商店" title="主题商店" />
-            <Link href="#显示工具提示" title="工具提示是一个有用的工具,它可以在文字缩略时展示全部内容。" />
-        </Anchor>
-        <br />
-        <div>position可以设置工具提示的位置</div>
-        <Anchor showTooltip={true} position={'right'}>
-            <Link href="#组件" title="组件" />
-            <Link href="#设计语言" title="设计语言" />
-            <Link href="#物料平台" title="物料平台" />
-            <Link href="#主题商店" title="主题商店" />
-            <Link href="#工具提示位置" title="工具提示是一个有用的工具,它可以在文字缩略时展示全部内容。" />
-        </Anchor>
-    </div>
-));
+export const showTooltip = () => (
+  <div>
+    <div>工具提示可以在 Link 超出最大宽度时显示 Link 的文字内容</div>
+    <br />
+    <Anchor showTooltip={true}>
+      <Link href="#组件" title="组件" />
+      <Link href="#设计语言" title="设计语言" />
+      <Link href="#物料平台" title="物料平台" />
+      <Link href="#主题商店" title="主题商店" />
+      <Link
+        href="#显示工具提示"
+        title="工具提示是一个有用的工具,它可以在文字缩略时展示全部内容。"
+      />
+    </Anchor>
+    <br />
+    <div>position可以设置工具提示的位置</div>
+    <Anchor showTooltip={true} position={'right'}>
+      <Link href="#组件" title="组件" />
+      <Link href="#设计语言" title="设计语言" />
+      <Link href="#物料平台" title="物料平台" />
+      <Link href="#主题商店" title="主题商店" />
+      <Link
+        href="#工具提示位置"
+        title="工具提示是一个有用的工具,它可以在文字缩略时展示全部内容。"
+      />
+    </Anchor>
+  </div>
+);
 
-stories.add('max-height', () => (
-    <div>
-        <div>设置 maxHeight 可以控制 Anchor 的高度,滚动显示 Anchor 内容</div>
-        <br />
-        <Anchor maxHeight={'100px'}>
-            <Link href="#组件" title="组件" />
-            <Link href="#设计语言" title="设计语言" />
-            <Link href="#物料平台" title="物料平台" />
-            <Link href="#主题商店" title="主题商店" />
-            <Link href="#显示工具提示" title="工具提示是一个有用的工具,它可以在文字缩略时展示全部内容。" />
-        </Anchor>
-    </div>
-));
+export const MaxHeight = () => (
+  <div>
+    <div>设置 maxHeight 可以控制 Anchor 的高度,滚动显示 Anchor 内容</div>
+    <br />
+    <Anchor maxHeight={'100px'}>
+      <Link href="#组件" title="组件" />
+      <Link href="#设计语言" title="设计语言" />
+      <Link href="#物料平台" title="物料平台" />
+      <Link href="#主题商店" title="主题商店" />
+      <Link
+        href="#显示工具提示"
+        title="工具提示是一个有用的工具,它可以在文字缩略时展示全部内容。"
+      />
+    </Anchor>
+  </div>
+);
 
-stories.add('定位方式', () => (
-    <div>
-        <Anchor style={{ position: 'absolute', right: 0 }} scrollMotion={false} getContainer={getContainer}>
-            <Link href="#welcome" title="welcome" />
-            <Link href="#api" title="api too much to show">
-                <Link href="#docs" title="docs">
-                    <Link href="#doc1" title="doc1" />
-                    <Link href="#doc2" title="doc2" />
-                </Link>
-            </Link>
-            <Link href="#contact" title="contact" />
-        </Anchor>
+export const StylePosition = () => (
+  <div>
+    <Anchor
+      style={{ position: 'absolute', right: 0 }}
+      scrollMotion={false}
+      getContainer={getContainer}
+    >
+      <Link href="#welcome" title="welcome" />
+      <Link href="#api" title="api too much to show">
+        <Link href="#docs" title="docs">
+          <Link href="#doc1" title="doc1" />
+          <Link href="#doc2" title="doc2" />
+        </Link>
+      </Link>
+      <Link href="#contact" title="contact" />
+    </Anchor>
 
-        <div>设置style对象可以改变 Anchor 组件的定位方式,右边就是个 fixed 的 Anchor</div>
-        <div id="box" style={{ height: '500px', overflow: 'scroll' }}>
-            <h1 id="welcome" style={{ height: '300px' }}>
-                Welcome
-            </h1>
-            <h1 id="api" style={{ height: '300px' }}>
-                API
-            </h1>
-            <h2 id="docs" style={{ height: '200px' }}>
-                Docs
-            </h2>
-            <h3 id="doc1" style={{ height: '100px' }}>
-                Doc1
-            </h3>
-            <h3 id="doc2" style={{ height: '100px' }}>
-                Doc2
-            </h3>
-            <h1 id="contact" style={{ height: '300px' }}>
-                Contact me
-            </h1>
-        </div>
+    <div>设置style对象可以改变 Anchor 组件的定位方式,右边就是个 fixed 的 Anchor</div>
+    <div id="box" style={{ height: '500px', overflow: 'scroll' }}>
+      <h1 id="welcome" style={{ height: '300px' }}>
+        Welcome
+      </h1>
+      <h1 id="api" style={{ height: '300px' }}>
+        API
+      </h1>
+      <h2 id="docs" style={{ height: '200px' }}>
+        Docs
+      </h2>
+      <h3 id="doc1" style={{ height: '100px' }}>
+        Doc1
+      </h3>
+      <h3 id="doc2" style={{ height: '100px' }}>
+        Doc2
+      </h3>
+      <h1 id="contact" style={{ height: '300px' }}>
+        Contact me
+      </h1>
     </div>
-));
+  </div>
+);
 
-stories.add('targetOffset', () => (
-    <div>
-        <Anchor style={{ position: 'absolute', right: 0, top: 100 }} targetOffset={100} scrollMotion={true} getContainer={getContainer}>
-            <Link href="#welcome" title="welcome" />
-            <Link href="#api" title="api too much to show">
-                <Link href="#docs" title="docs">
-                    <Link href="#doc1" title="doc1" />
-                    <Link href="#doc2" title="doc2" />
-                </Link>
-            </Link>
-            <Link href="#contact" title="contact" />
-        </Anchor>
+export const TargetOffset = () => (
+  <div>
+    <Anchor
+      style={{ position: 'absolute', right: 0, top: 100 }}
+      targetOffset={100}
+      scrollMotion={true}
+      getContainer={getContainer}
+    >
+      <Link href="#welcome" title="welcome" />
+      <Link href="#api" title="api too much to show">
+        <Link href="#docs" title="docs">
+          <Link href="#doc1" title="doc1" />
+          <Link href="#doc2" title="doc2" />
+        </Link>
+      </Link>
+      <Link href="#contact" title="contact" />
+    </Anchor>
 
-        <div id="box" style={{ height: '500px', overflow: 'scroll', border: '1px solid #eee' }}>
-            <div style={{ position: 'fixed', border: '1px solid red', height: 100, width: '100%' }}>这是 fixed 的一段话</div>
-            <h1 style={{ height: '300px' }}>
-                whatever
-            </h1>
-            <h1 id="welcome" style={{ height: '300px' }}>
-                Welcome
-            </h1>
-            <h1 id="api" style={{ height: '300px' }}>
-                API
-            </h1>
-            <h2 id="docs" style={{ height: '200px' }}>
-                Docs
-            </h2>
-            <h3 id="doc1" style={{ height: '100px' }}>
-                Doc1
-            </h3>
-            <h3 id="doc2" style={{ height: '100px' }}>
-                Doc2
-            </h3>
-            <h1 id="contact" style={{ height: '300px' }}>
-                Contact me
-            </h1>
-        </div>
+    <div id="box" style={{ height: '500px', overflow: 'scroll', border: '1px solid #eee' }}>
+      <div style={{ position: 'fixed', border: '1px solid red', height: 100, width: '100%' }}>
+        这是 fixed 的一段话
+      </div>
+      <h1 style={{ height: '300px' }}>whatever</h1>
+      <h1 id="welcome" style={{ height: '300px' }}>
+        Welcome
+      </h1>
+      <h1 id="api" style={{ height: '300px' }}>
+        API
+      </h1>
+      <h2 id="docs" style={{ height: '200px' }}>
+        Docs
+      </h2>
+      <h3 id="doc1" style={{ height: '100px' }}>
+        Doc1
+      </h3>
+      <h3 id="doc2" style={{ height: '100px' }}>
+        Doc2
+      </h3>
+      <h1 id="contact" style={{ height: '300px' }}>
+        Contact me
+      </h1>
     </div>
-));
+  </div>
+);
 
-stories.add('fix container scroll bug #1158', () => (
-    <div style={{ height: '120vh' }}>
-        <div style={{ width: 500, height: 500, position: 'relative', overflowY: 'scroll' }}>
-            <Anchor style={{ position: 'absolute', right: 0 }} scrollMotion={true} getContainer={getContainer}>
-                <Link href="#welcome" title="welcome" />
-                <Link href="#api" title="api too much to show">
-                    <Link href="#docs" title="docs">
-                        <Link href="#doc1" title="doc1" />
-                        <Link href="#doc2" title="doc2" />
-                    </Link>
-                </Link>
-                <Link href="#contact" title="contact" />
-            </Anchor>
+export const FixContainerScrollBug1158 = () => (
+  <div style={{ height: '120vh' }}>
+    <div style={{ width: 500, height: 500, position: 'relative', overflowY: 'scroll' }}>
+      <Anchor
+        style={{ position: 'absolute', right: 0 }}
+        scrollMotion={true}
+        getContainer={getContainer}
+      >
+        <Link href="#welcome" title="welcome" />
+        <Link href="#api" title="api too much to show">
+          <Link href="#docs" title="docs">
+            <Link href="#doc1" title="doc1" />
+            <Link href="#doc2" title="doc2" />
+          </Link>
+        </Link>
+        <Link href="#contact" title="contact" />
+      </Anchor>
 
-            <div id="box" style={{ height: 700, overflowY: 'scroll' }}>
-                <h1 id="welcome" style={{ height: '300px' }}>
-                    Welcome
-                </h1>
-                <h1 id="api" style={{ height: '300px' }}>
-                    API
-                </h1>
-                <h2 id="docs" style={{ height: '200px' }}>
-                    Docs
-                </h2>
-                <h3 id="doc1" style={{ height: '100px' }}>
-                    Doc1
-                </h3>
-                <h3 id="doc2" style={{ height: '100px' }}>
-                    Doc2
-                </h3>
-                <h1 id="contact" style={{ height: '300px' }}>
-                    Contact me
-                </h1>
-            </div>
-        </div>
+      <div id="box" style={{ height: 700, overflowY: 'scroll' }}>
+        <h1 id="welcome" style={{ height: '300px' }}>
+          Welcome
+        </h1>
+        <h1 id="api" style={{ height: '300px' }}>
+          API
+        </h1>
+        <h2 id="docs" style={{ height: '200px' }}>
+          Docs
+        </h2>
+        <h3 id="doc1" style={{ height: '100px' }}>
+          Doc1
+        </h3>
+        <h3 id="doc2" style={{ height: '100px' }}>
+          Doc2
+        </h3>
+        <h1 id="contact" style={{ height: '300px' }}>
+          Contact me
+        </h1>
+      </div>
     </div>
-));
+  </div>
+);

+ 306 - 305
packages/semi-ui/autoComplete/_story/autoComplete.stories.js

@@ -1,348 +1,349 @@
-import React, { Component, useState, useDebugValue } from 'react';
-import { storiesOf } from '@storybook/react'; // import { withKnobs, text, boolean } from '@storybook/addon-knobs';
+import React, { Component, useState } from 'react';
 
-import withPropsCombinations from 'react-storybook-addon-props-combinations';
-import { Button, TextArea, Icon } from '../../index';
 import CustomTrigger from './CustomTrigger';
 import AutoComplete from '../index';
-import { result } from 'lodash';
 import { IconSearch } from '@douyinfe/semi-icons';
-const stories = storiesOf('AutoComplete', module); // stories.addDecorator(withKnobs);;
+
+export default {
+  title: 'AutoComplete',
+  parameters: {
+    chromatic: { disableSnapshot: true },
+  },
+}
 
 const props = {
-    onBlur: (v, e) => {
-        console.log('onBlur');
-        console.log(v, e);
-    },
-    onFocus: (v, e) => {
-        console.log('onFocus');
-        console.log(v, e);
-    },
+  onBlur: (v, e) => {
+    console.log('onBlur');
+    console.log(v, e);
+  },
+  onFocus: (v, e) => {
+    console.log('onFocus');
+    console.log(v, e);
+  },
 };
 
 class Demo extends React.Component {
-    constructor() {
-        super();
-        this.state = {
-            data: [],
-            data2: ['mike', 'tony', 'steve'],
-        };
-        this.acref = React.createRef();
+  constructor() {
+    super();
+    this.state = {
+      data: [],
+      data2: ['mike', 'tony', 'steve'],
+    };
+    this.acref = React.createRef();
+  }
+
+  handleSearch(value) {
+    // let data =  !value ? [] : [value, value + value, value + value + value];
+    let result; // if (!value || value.indexOf('@') >= 0) {
+    //     result = [];
+    // } else {
+
+    if (value) {
+      result = ['gmail.com', '163.com', 'qq.com'].map(domain => `${value}@${domain}`);
+    } else {
+      result = [];
+    } // }
+
+    this.setState({
+      data: result,
+    });
+  }
+
+  handleSearch2(value) {
+    // let data2 =  !value ? [] : [value, value + value, value + value + value];
+    let result;
+
+    if (!value || value.indexOf('@') >= 0) {
+      result = [];
+    } else {
+      result = ['gmail.com', '163.com', 'qq.com'].map(domain => `${value}@${domain}`);
     }
 
-    handleSearch(value) {
-        // let data =  !value ? [] : [value, value + value, value + value + value];
-        let result; // if (!value || value.indexOf('@') >= 0) {
-        //     result = [];
-        // } else {
-
-        if (value) {
-            result = ['gmail.com', '163.com', 'qq.com'].map(domain => `${value}@${domain}`);
-        } else {
-            result = [];
-        } // }
-
-        this.setState({
-            data: result,
-        });
-    }
+    this.setState({
+      data2: result,
+    });
+  }
+
+  render() {
+    const { data, data2 } = this.state;
+    return (
+      <div>
+        <AutoComplete
+          placeholder="fe"
+          className="test-ac"
+          prefix={<IconSearch />}
+          showClear
+          data={data}
+          style={{
+            width: 300,
+          }}
+          onSearch={this.handleSearch.bind(this)}
+          onSelect={v => console.log(v)}
+          {...props}
+          ref={this.acref}
+        />
+      </div>
+    );
+  }
+}
 
-    handleSearch2(value) {
-        // let data2 =  !value ? [] : [value, value + value, value + value + value];
-        let result;
+export const BasicUsage = () => <Demo />;
 
-        if (!value || value.indexOf('@') >= 0) {
-            result = [];
-        } else {
-            result = ['gmail.com', '163.com', 'qq.com'].map(domain => `${value}@${domain}`);
-        }
+class CustomOptionDemo extends Component {
+  constructor(props) {
+    super(props);
+    this.state = {
+      data: [],
+      data2: [],
+    };
+  }
 
-        this.setState({
-            data2: result,
-        });
-    }
+  search = value => {
+    let result;
 
-    render() {
-        const { data, data2 } = this.state;
-        return (
-            <div>
-                <AutoComplete
-                    placeholder="fe"
-                    className="test-ac"
-                    prefix={<IconSearch />}
-                    showClear
-                    data={data}
-                    style={{
-                        width: 300,
-                    }}
-                    onSearch={this.handleSearch.bind(this)}
-                    onSelect={v => console.log(v)}
-                    {...props}
-                    ref={this.acref}
-                />
-            </div>
-        );
+    if (!value) {
+      result = [];
+    } else {
+      result = ['gmail.com', '163.com', 'qq.com'].map(domain => `${value}@${domain}`);
     }
-}
-
-stories.add('基本使用', () => <Demo />);
 
-class CustomOptionDemo extends Component {
-    constructor(props) {
-        super(props);
-        this.state = {
-            data: [],
-            data2: [],
+    this.setState({
+      data: result,
+    });
+  };
+  renderOption = item => {
+    return (
+      <>
+        <span
+          style={{
+            color: 'pink',
+          }}
+        >
+          邮箱
+        </span>
+        : <span>{item}</span>
+      </>
+    );
+  };
+  search2 = value => {
+    let result;
+
+    if (!value) {
+      result = [];
+    } else {
+      result = ['gmail.com', '163.com', 'qq.com'].map(domain => {
+        return {
+          email: `${value}@${domain}`,
+          time: new Date().valueOf(),
+          value: `${value}@${domain}`,
         };
+      });
     }
 
-    search = value => {
-        let result;
-
-        if (!value) {
-            result = [];
-        } else {
-            result = ['gmail.com', '163.com', 'qq.com'].map(domain => `${value}@${domain}`);
-        }
-
-        this.setState({
-            data: result,
-        });
-    };
-    renderOption = item => {
-        return (
-            <>
-                <span
-                    style={{
-                        color: 'pink',
-                    }}
-                >
-                    邮箱
-                </span>
-                : <span>{item}</span>
-            </>
-        );
-    };
-    search2 = value => {
-        let result;
-
-        if (!value) {
-            result = [];
-        } else {
-            result = ['gmail.com', '163.com', 'qq.com'].map(domain => {
-                return {
-                    email: `${value}@${domain}`,
-                    time: new Date().valueOf(),
-                    value: `${value}@${domain}`,
-                };
-            });
-        }
-
-        this.setState({
-            data2: result,
-        });
-    };
-    renderObjectOption = item => {
-        return (
-            <div>
-                <span
-                    style={{
-                        color: 'pink',
-                    }}
-                >
-                    邮箱
-                </span>
-                : <span>{item.email}</span>
-                <span>time</span>: <span>{item.time}</span>
-            </div>
-        );
-    };
-
-    render() {
-        return (
-            <>
-                <AutoComplete
-                    showClear
-                    data={this.state.data}
-                    renderItem={this.renderOption}
-                    style={{
-                        width: '250px',
-                    }}
-                    optionLabelProp="value"
-                    onSearch={this.search}
-                ></AutoComplete>
-                <br />
-                <br />
-                <AutoComplete
-                    onChangeWithObject
-                    style={{
-                        width: '250px',
-                    }}
-                    renderItem={this.renderObjectOption}
-                    renderSelectedItem={node => node.email}
-                    data={this.state.data2}
-                    onSearch={this.search2}
-                />
-            </>
-        );
-    }
+    this.setState({
+      data2: result,
+    });
+  };
+  renderObjectOption = item => {
+    return (
+      <div>
+        <span
+          style={{
+            color: 'pink',
+          }}
+        >
+          邮箱
+        </span>
+        : <span>{item.email}</span>
+        <span>time</span>: <span>{item.time}</span>
+      </div>
+    );
+  };
+
+  render() {
+    return (
+      <>
+        <AutoComplete
+          showClear
+          data={this.state.data}
+          renderItem={this.renderOption}
+          style={{
+            width: '250px',
+          }}
+          optionLabelProp="value"
+          onSearch={this.search}
+        ></AutoComplete>
+        <br />
+        <br />
+        <AutoComplete
+          onChangeWithObject
+          style={{
+            width: '250px',
+          }}
+          renderItem={this.renderObjectOption}
+          renderSelectedItem={node => node.email}
+          data={this.state.data2}
+          onSearch={this.search2}
+        />
+      </>
+    );
+  }
 }
 
-stories.add('自定义选项内容', () => <CustomOptionDemo />);
+export const RenderItem = () => <CustomOptionDemo />;
 
 class WithDefaultValue extends React.Component {
-    constructor() {
-        super();
-        this.state = {
-            data: ['[email protected]', '[email protected]', '[email protected]'],
-        };
-        this.onSearch = this.onSearch.bind(this);
-    }
-    onSearch(value) {
-        let result;
-
-        if (!value) {
-            result = [];
-        } else {
-            result = ['gmail.com', '163.com', 'qq.com'].map(domain => `${value}@${domain}`);
-        }
-
-        this.setState({
-            data: result,
-        });
+  constructor() {
+    super();
+    this.state = {
+      data: ['[email protected]', '[email protected]', '[email protected]'],
+    };
+    this.onSearch = this.onSearch.bind(this);
+  }
+  onSearch(value) {
+    let result;
+
+    if (!value) {
+      result = [];
+    } else {
+      result = ['gmail.com', '163.com', 'qq.com'].map(domain => `${value}@${domain}`);
     }
 
-    render() {
-        let { data } = this.state;
-        return (
-            <>
-                {/* <AutoComplete
+    this.setState({
+      data: result,
+    });
+  }
+
+  render() {
+    let { data } = this.state;
+    return (
+      <>
+        {/* <AutoComplete
            defaultValue='[email protected]'
            data={data}
            onSearch={this.onSearch}
         /> */}
 
-                <AutoComplete defaultValue="semi" data={data} onSearch={this.onSearch} />
-            </>
-        );
-    }
+        <AutoComplete defaultValue="semi" data={data} onSearch={this.onSearch} />
+      </>
+    );
+  }
 }
 
-stories.add('defaultValue', () => <WithDefaultValue />);
+export const DefaultValue = () => <WithDefaultValue />;
 
 class ControlledMode extends React.Component {
-    constructor() {
-        super();
-        this.state = {
-            data: [],
-            dataObject: [],
-            value: '',
-        };
-        this.onSearch = this.onSearch.bind(this);
-        this.onChange = this.onChange.bind(this);
-    }
-
-    onSearch(value) {
-        let result, resultObject;
-
-        if (!value) {
-            result = [];
-            resultObject = [];
-        } else {
-            result = ['gmail.com', '163.com', 'qq.com'].map(domain => `${value}@${domain}`);
-            resultObject = ['gmail.com', '163.com', 'qq.com'].map(domain => ({
-                label: `${value}@${domain}`,
-                value: `${value}@${domain}`,
-            }));
-        }
-
-        this.setState({
-            data: result,
-            dataObject: resultObject,
-        });
-    }
-
-    onChange(value) {
-        this.setState({
-            value: value,
-        });
+  constructor() {
+    super();
+    this.state = {
+      data: [],
+      dataObject: [],
+      value: '',
+    };
+    this.onSearch = this.onSearch.bind(this);
+    this.onChange = this.onChange.bind(this);
+  }
+
+  onSearch(value) {
+    let result, resultObject;
+
+    if (!value) {
+      result = [];
+      resultObject = [];
+    } else {
+      result = ['gmail.com', '163.com', 'qq.com'].map(domain => `${value}@${domain}`);
+      resultObject = ['gmail.com', '163.com', 'qq.com'].map(domain => ({
+        label: `${value}@${domain}`,
+        value: `${value}@${domain}`,
+      }));
     }
 
-    render() {
-        let { data, value, dataObject } = this.state;
-        return (
-            <>
-                <AutoComplete
-                    showClear
-                    value={value}
-                    data={data}
-                    onChange={this.onChange}
-                    onSearch={this.onSearch}
-                    style={{
-                        width: 200,
-                    }}
-                />
-                <br />
-                <AutoComplete
-                    showClear
-                    value={value}
-                    data={dataObject}
-                    onChange={this.onChange}
-                    onSearch={this.onSearch}
-                    style={{
-                        width: 200,
-                    }}
-                />
-                <br />
-                <AutoComplete
-                    defaultValue={'hello semi'}
-                    showClear
-                    value={value}
-                    data={dataObject}
-                    onChange={this.onChange}
-                    onSearch={this.onSearch}
-                    style={{
-                        width: 200,
-                    }}
-                />
-            </>
-        );
-    }
+    this.setState({
+      data: result,
+      dataObject: resultObject,
+    });
+  }
+
+  onChange(value) {
+    this.setState({
+      value: value,
+    });
+  }
+
+  render() {
+    let { data, value, dataObject } = this.state;
+    return (
+      <>
+        <AutoComplete
+          showClear
+          value={value}
+          data={data}
+          onChange={this.onChange}
+          onSearch={this.onSearch}
+          style={{
+            width: 200,
+          }}
+        />
+        <br />
+        <AutoComplete
+          showClear
+          value={value}
+          data={dataObject}
+          onChange={this.onChange}
+          onSearch={this.onSearch}
+          style={{
+            width: 200,
+          }}
+        />
+        <br />
+        <AutoComplete
+          defaultValue={'hello semi'}
+          showClear
+          value={value}
+          data={dataObject}
+          onChange={this.onChange}
+          onSearch={this.onSearch}
+          style={{
+            width: 200,
+          }}
+        />
+      </>
+    );
+  }
 }
 
-const EmptyContent = () => {
-    let [data, setData] = useState([]);
-    const [loading, setLoading] = useState(false);
-
-    const fetchData = v => {
-        setLoading(true);
-        setTimeout(() => {
-            if (!v) {
-                setData([]);
-                setLoading(false);
-                return;
-            }
-
-            setData(() => {
-                const res = Array.from(Array(5)).map(c => Math.random());
-                return res;
-            });
-            setLoading(false);
-        }, 1000);
-    };
-
-    return <AutoComplete loading={loading} data={data} emptyContent={'空数据'} onSearch={fetchData} />;
+export const EmptyContent = () => {
+  let [data, setData] = useState([]);
+  const [loading, setLoading] = useState(false);
+
+  const fetchData = v => {
+    setLoading(true);
+    setTimeout(() => {
+      if (!v) {
+        setData([]);
+        setLoading(false);
+        return;
+      }
+
+      setData(() => {
+        const res = Array.from(Array(5)).map(c => Math.random());
+        return res;
+      });
+      setLoading(false);
+    }, 1000);
+  };
+
+  return (
+    <AutoComplete loading={loading} data={data} emptyContent={'空数据'} onSearch={fetchData} />
+  );
 };
 
-const AutoFocus = () => {
-    return <AutoComplete autoFocus />;
+export const AutoFocus = () => {
+  return <AutoComplete autoFocus />;
 };
 
-stories.add('value受控', () => <ControlledMode />);
-stories.add('远程搜索', () => <Demo />);
-stories.add(`CustomTrigger`, () => <CustomTrigger />);
-stories.add(`Disabled`, () => {
-    return <AutoComplete disabled />;
-});
-stories.add('emptyContent配合远程搜索数据展示', () => <EmptyContent />);
-stories.add('autofocus', () => <AutoFocus />);
+export const ControlledValue = () => <ControlledMode />;
+
+export const CustomTriggerDemo = () => <CustomTrigger />;
+
+export const Disabled = () => <AutoComplete disabled />;

+ 173 - 152
packages/semi-ui/avatar/_story/avatar.stories.js

@@ -1,170 +1,191 @@
 import React from 'react';
-import { storiesOf } from '@storybook/react';
-// import { withKnobs, text, boolean } from '@storybook/addon-knobs';
-import withPropsCombinations from 'react-storybook-addon-props-combinations';
-
 import Avatar from '../index';
 import Popover from '../../popover/index';
 import AvatarGroup from '../avatarGroup';
 
-const stories = storiesOf('Avatar', module);
-
-// stories.addDecorator(withKnobs);;
+export default {
+  title: 'Avatar',
+}
 
-stories.add('avatar', () => (
+export const Basic = () => (
+  <div>
     <div>
-        <div>
-            <Avatar>U</Avatar>
-            <Avatar size="large">U</Avatar>
-            <Avatar size="extra-small" >U</Avatar>
-            <Avatar size="small">U</Avatar>
-            <Avatar size="default">U</Avatar>
-            <Avatar size="extra-large">U</Avatar>
-        </div>
-        <div>
-            <Avatar shape="square" >U</Avatar>
-            <Avatar shape="square" size="large">U</Avatar>
-            <Avatar shape="square" size="extra-small">U</Avatar>
-            <Avatar shape="square" size="small">U</Avatar>
-            <Avatar shape="square" size="default">U</Avatar>
-            <Avatar shape="square" size="extra-large">U</Avatar>
-        </div>
+      <Avatar>U</Avatar>
+      <Avatar size="large">U</Avatar>
+      <Avatar size="extra-small">U</Avatar>
+      <Avatar size="small">U</Avatar>
+      <Avatar size="default">U</Avatar>
+      <Avatar size="extra-large">U</Avatar>
     </div>
-));
-
-stories.add('custom avatar', () => (
     <div>
-        <Avatar>U</Avatar>
-        <Avatar color='red'>U</Avatar>
-        <Avatar color='red' size="default">DF</Avatar>
-        <Avatar src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" />
-        <Avatar size="default" src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" />
-        <Avatar size="small" src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" />
-        <Avatar style={{ color: '#f56a00', backgroundColor: '#fde3cf' }}>U</Avatar>
-        <Avatar style={{ backgroundColor: '#87d068' }} >YZ</Avatar>
+      <Avatar shape="square">U</Avatar>
+      <Avatar shape="square" size="large">
+        U
+      </Avatar>
+      <Avatar shape="square" size="extra-small">
+        U
+      </Avatar>
+      <Avatar shape="square" size="small">
+        U
+      </Avatar>
+      <Avatar shape="square" size="default">
+        U
+      </Avatar>
+      <Avatar shape="square" size="extra-large">
+        U
+      </Avatar>
     </div>
-));
+  </div>
+);
 
-stories.add('avatar group', () => (
-    <div>
-        <p>medium</p>
-        <AvatarGroup>
-            <Avatar color='red'>LL</Avatar>
-            <Avatar >CX</Avatar>
-            <Avatar size="default">CX</Avatar>
-            <Avatar color='amber'>RM</Avatar>
-            <Avatar style={{ color: '#f56a00', backgroundColor: '#fde3cf' }}>ZL</Avatar>
-            <Avatar style={{ backgroundColor: '#87d068' }} >YZ</Avatar>
-        </AvatarGroup>
-        <p>default</p>
-        <AvatarGroup size="default">
-            <Avatar color='red'>LL</Avatar>
-            <Avatar >CX</Avatar>
-            <Avatar size="default">CX</Avatar>
-            <Avatar color='amber'>RM</Avatar>
-            <Avatar style={{ color: '#f56a00', backgroundColor: '#fde3cf' }}>ZL</Avatar>
-            <Avatar style={{ backgroundColor: '#87d068' }} >YZ</Avatar>
-        </AvatarGroup>
-        <p>small</p>
-        <AvatarGroup size="small">
-            <Avatar color='red'>LL</Avatar>
-            <Avatar >CX</Avatar>
-            <Avatar size="default">CX</Avatar>
-            <Avatar color='amber'>RM</Avatar>
-            <Avatar style={{ color: '#f56a00', backgroundColor: '#fde3cf' }}>ZL</Avatar>
-            <Avatar style={{ backgroundColor: '#87d068' }} >YZ</Avatar>
-        </AvatarGroup>
-    </div>
-));
+export const CustomAvatar = () => (
+  <div>
+    <Avatar>U</Avatar>
+    <Avatar color="red">U</Avatar>
+    <Avatar color="red" size="default">
+      DF
+    </Avatar>
+    <Avatar src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" />
+    <Avatar size="default" src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" />
+    <Avatar size="small" src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" />
+    <Avatar style={{ color: '#f56a00', backgroundColor: '#fde3cf' }}>U</Avatar>
+    <Avatar style={{ backgroundColor: '#87d068' }}>YZ</Avatar>
+  </div>
+);
 
-stories.add('avatar group 头像覆盖方式', () => (
-    <div>
-        <div>overlapFrom=start</div>
-        <AvatarGroup overlapFrom={'start'}>
-            <Avatar color='red'>LL</Avatar>
-            <Avatar >CX</Avatar>
-            <Avatar color='amber'>RM</Avatar>
-            <Avatar style={{ color: '#f56a00', backgroundColor: '#fde3cf' }}>ZL</Avatar>
-            <Avatar style={{ backgroundColor: '#87d068' }} >YZ</Avatar>
-        </AvatarGroup><br /><br />
-        <div>overlapFrom=end</div>
-        <AvatarGroup overlapFrom={'end'}>
-            <Avatar color='red'>LL</Avatar>
-            <Avatar >CX</Avatar>
-            <Avatar color='amber'>RM</Avatar>
-            <Avatar style={{ color: '#f56a00', backgroundColor: '#fde3cf' }}>ZL</Avatar>
-            <Avatar style={{ backgroundColor: '#87d068' }} >YZ</Avatar>
-        </AvatarGroup><br /><br />
-    </div>
-));
+export const GroupSize = () => (
+  <div>
+    <p>medium</p>
+    <AvatarGroup>
+      <Avatar color="red">LL</Avatar>
+      <Avatar>CX</Avatar>
+      <Avatar size="default">CX</Avatar>
+      <Avatar color="amber">RM</Avatar>
+      <Avatar style={{ color: '#f56a00', backgroundColor: '#fde3cf' }}>ZL</Avatar>
+      <Avatar style={{ backgroundColor: '#87d068' }}>YZ</Avatar>
+    </AvatarGroup>
+    <p>default</p>
+    <AvatarGroup size="default">
+      <Avatar color="red">LL</Avatar>
+      <Avatar>CX</Avatar>
+      <Avatar size="default">CX</Avatar>
+      <Avatar color="amber">RM</Avatar>
+      <Avatar style={{ color: '#f56a00', backgroundColor: '#fde3cf' }}>ZL</Avatar>
+      <Avatar style={{ backgroundColor: '#87d068' }}>YZ</Avatar>
+    </AvatarGroup>
+    <p>small</p>
+    <AvatarGroup size="small">
+      <Avatar color="red">LL</Avatar>
+      <Avatar>CX</Avatar>
+      <Avatar size="default">CX</Avatar>
+      <Avatar color="amber">RM</Avatar>
+      <Avatar style={{ color: '#f56a00', backgroundColor: '#fde3cf' }}>ZL</Avatar>
+      <Avatar style={{ backgroundColor: '#87d068' }}>YZ</Avatar>
+    </AvatarGroup>
+  </div>
+);
 
-stories.add('avatar group 最大显示头像数', () => (
-    <div>
-        <div>maxCount=3</div>
-        <AvatarGroup maxCount={3}>
-            <Avatar color='red'>LL</Avatar>
-            <Avatar >CX</Avatar>
-            <Avatar color='amber'>RM</Avatar>
-            <Avatar style={{ color: '#f56a00', backgroundColor: '#fde3cf' }}>ZL</Avatar>
-            <Avatar style={{ backgroundColor: '#87d068' }} >YZ</Avatar>
-        </AvatarGroup><br /><br />
-    </div>
-));
+export const OverlapFromDemo = () => (
+  <div>
+    <div>overlapFrom=start</div>
+    <AvatarGroup overlapFrom={'start'}>
+      <Avatar color="red">LL</Avatar>
+      <Avatar>CX</Avatar>
+      <Avatar color="amber">RM</Avatar>
+      <Avatar style={{ color: '#f56a00', backgroundColor: '#fde3cf' }}>ZL</Avatar>
+      <Avatar style={{ backgroundColor: '#87d068' }}>YZ</Avatar>
+    </AvatarGroup>
+    <br />
+    <br />
+    <div>overlapFrom=end</div>
+    <AvatarGroup overlapFrom={'end'}>
+      <Avatar color="red">LL</Avatar>
+      <Avatar>CX</Avatar>
+      <Avatar color="amber">RM</Avatar>
+      <Avatar style={{ color: '#f56a00', backgroundColor: '#fde3cf' }}>ZL</Avatar>
+      <Avatar style={{ backgroundColor: '#87d068' }}>YZ</Avatar>
+    </AvatarGroup>
+    <br />
+    <br />
+  </div>
+);
+
+export const MaxCountDemo = () => (
+  <div>
+    <div>maxCount=3</div>
+    <AvatarGroup maxCount={3}>
+      <Avatar color="red">LL</Avatar>
+      <Avatar>CX</Avatar>
+      <Avatar color="amber">RM</Avatar>
+      <Avatar style={{ color: '#f56a00', backgroundColor: '#fde3cf' }}>ZL</Avatar>
+      <Avatar style={{ backgroundColor: '#87d068' }}>YZ</Avatar>
+    </AvatarGroup>
+    <br />
+    <br />
+  </div>
+);
 
 const renderMore = (restNumber, restAvatars) => {
-    const content = (
-        restAvatars.map((avatar, index) => {
-            return (
-                <div style={{ paddingBottom: '12px' }}>
-                    {React.cloneElement(avatar, { size: 'extra-small' })}
-                    <span style={{ marginLeft: 8, fontSize: 14 }}>这是段文字描述</span>
-                </div>
-            );
-        })
-    );
+  const content = restAvatars.map((avatar, index) => {
     return (
-        <Popover content={content} autoAdjustOverflow={false} position={'bottomRight'} style={{ padding: '12px 8px', paddingBottom: 0 }}>
-            <Avatar>
-                {`+${restNumber}`}
-            </Avatar>
-        </Popover>
-    )
-}
+      <div style={{ paddingBottom: '12px' }}>
+        {React.cloneElement(avatar, { size: 'extra-small' })}
+        <span style={{ marginLeft: 8, fontSize: 14 }}>这是段文字描述</span>
+      </div>
+    );
+  });
+  return (
+    <Popover
+      content={content}
+      autoAdjustOverflow={false}
+      position={'bottomRight'}
+      style={{ padding: '12px 8px', paddingBottom: 0 }}
+    >
+      <Avatar>{`+${restNumber}`}</Avatar>
+    </Popover>
+  );
+};
 
-stories.add('avatar group 自定义渲染 more 标签', () => (
-    <div>
-        <AvatarGroup maxCount={3} renderMore={renderMore}>
-            <Avatar color='red'>LL</Avatar>
-            <Avatar >CX</Avatar>
-            <Avatar color='amber'>RM</Avatar>
-            <Avatar style={{ color: '#f56a00', backgroundColor: '#fde3cf' }}>ZL</Avatar>
-            <Avatar style={{ backgroundColor: '#87d068' }} >YZ</Avatar>
-        </AvatarGroup><br /><br />
-    </div>
-));
+export const RenderMoreDemo = () => (
+  <div>
+    <AvatarGroup maxCount={3} renderMore={renderMore}>
+      <Avatar color="red">LL</Avatar>
+      <Avatar>CX</Avatar>
+      <Avatar color="amber">RM</Avatar>
+      <Avatar style={{ color: '#f56a00', backgroundColor: '#fde3cf' }}>ZL</Avatar>
+      <Avatar style={{ backgroundColor: '#87d068' }}>YZ</Avatar>
+    </AvatarGroup>
+    <br />
+    <br />
+  </div>
+);
 
-stories.add('avatar extra-extra-small overlap', () => (
-    <div>
-        <AvatarGroup size="extra-extra-small" overlapFrom={'start'}>
-            <Avatar color='red'>LL</Avatar>
-            <Avatar >CX</Avatar>
-            <Avatar color='amber'>RM</Avatar>
-            <Avatar style={{ color: '#f56a00', backgroundColor: '#fde3cf' }}>ZL</Avatar>
-            <Avatar style={{ backgroundColor: '#87d068' }} >YZ</Avatar>
-        </AvatarGroup><br/><br/>
-        <AvatarGroup size="extra-extra-small" overlapFrom={'end'}>
-            <Avatar color='red'>LL</Avatar>
-            <Avatar >CX</Avatar>
-            <Avatar color='amber'>RM</Avatar>
-            <Avatar style={{ color: '#f56a00', backgroundColor: '#fde3cf' }}>ZL</Avatar>
-            <Avatar style={{ backgroundColor: '#87d068' }} >YZ</Avatar>
-        </AvatarGroup><br/><br/>
-        <AvatarGroup size="extra-extra-small" maxCount={3}>
-            <Avatar color='red'>LL</Avatar>
-            <Avatar >CX</Avatar>
-            <Avatar color='amber'>RM</Avatar>
-            <Avatar style={{ color: '#f56a00', backgroundColor: '#fde3cf' }}>ZL</Avatar>
-            <Avatar style={{ backgroundColor: '#87d068' }} >YZ</Avatar>
-        </AvatarGroup>
-    </div>
-));
+export const ExtraExtraSmallOverlap = () => (
+  <div>
+    <AvatarGroup size="extra-extra-small" overlapFrom={'start'}>
+      <Avatar color="red">LL</Avatar>
+      <Avatar>CX</Avatar>
+      <Avatar color="amber">RM</Avatar>
+      <Avatar style={{ color: '#f56a00', backgroundColor: '#fde3cf' }}>ZL</Avatar>
+      <Avatar style={{ backgroundColor: '#87d068' }}>YZ</Avatar>
+    </AvatarGroup>
+    <br />
+    <br />
+    <AvatarGroup size="extra-extra-small" overlapFrom={'end'}>
+      <Avatar color="red">LL</Avatar>
+      <Avatar>CX</Avatar>
+      <Avatar color="amber">RM</Avatar>
+      <Avatar style={{ color: '#f56a00', backgroundColor: '#fde3cf' }}>ZL</Avatar>
+      <Avatar style={{ backgroundColor: '#87d068' }}>YZ</Avatar>
+    </AvatarGroup>
+    <br />
+    <br />
+    <AvatarGroup size="extra-extra-small" maxCount={3}>
+      <Avatar color="red">LL</Avatar>
+      <Avatar>CX</Avatar>
+      <Avatar color="amber">RM</Avatar>
+      <Avatar style={{ color: '#f56a00', backgroundColor: '#fde3cf' }}>ZL</Avatar>
+      <Avatar style={{ backgroundColor: '#87d068' }}>YZ</Avatar>
+    </AvatarGroup>
+  </div>
+);

+ 30 - 30
packages/semi-ui/backtop/_story/backtop.stories.js

@@ -1,37 +1,37 @@
 import React from 'react';
-import { storiesOf } from '@storybook/react'; // import { withKnobs, text, boolean } from '@storybook/addon-knobs';
 
-import withPropsCombinations from 'react-storybook-addon-props-combinations';
 import BackTop from '../index';
-import Icon from '../../icons';
 import { IconArrowUp } from '@douyinfe/semi-icons';
 
-const stories = storiesOf('BackTop', module); // stories.addDecorator(withKnobs);;
+export default {
+  title: 'BackTop',
+}
 
-stories.add('BackTop', () => (
-    <div>
-        <div style={{height: 1600, width: 300, background: 'grey'}}></div>
-        <BackTop visibilityHeight={-1} />
+export const Default = () => (
+  <div>
+    <div style={{ height: 1600, width: 300, background: 'grey' }}></div>
+    <BackTop visibilityHeight={-1} />
   </div>
-));
-stories.add('custom BackTop', () => (
-    <div>
-        <div
-            style={{
-                height: 1600,
-                width: 300,
-                background: 'grey',
-            }}
-        ></div>
-        <BackTop
-            style={{
-                height: 40,
-                width: 40,
-                backgroundColor: '#ddd',
-                paddingTop: 12,
-            }}
-        >
-            <IconArrowUp />
-        </BackTop>
-    </div>
-));
+);
+
+export const Custom = () => (
+  <div>
+    <div
+      style={{
+        height: 1600,
+        width: 300,
+        background: 'grey',
+      }}
+    ></div>
+    <BackTop
+      style={{
+        height: 40,
+        width: 40,
+        backgroundColor: '#ddd',
+        paddingTop: 12,
+      }}
+    >
+      <IconArrowUp />
+    </BackTop>
+  </div>
+);

+ 81 - 85
packages/semi-ui/badge/_story/badge.stories.js

@@ -1,95 +1,91 @@
 import React from 'react';
-import { storiesOf } from '@storybook/react';
-// import { withKnobs, text, boolean } from '@storybook/addon-knobs';
-
 import Badge from '../index';
-import Icon from '../../icons';
-
-const stories = storiesOf('Badge', module);
-
 
+export default {
+  title: 'Badge',
+}
 
 const style = {
-    width: '42px',
-    height: '42px',
-    borderRadius: '4px',
-    background: '#eee',
-    display: 'inline-block',
-    verticalAlign: 'middle',
+  width: '42px',
+  height: '42px',
+  borderRadius: '4px',
+  background: '#eee',
+  display: 'inline-block',
+  verticalAlign: 'middle',
 };
 
-stories.add('Badge default', () => (
-    <div>
-        <Badge count={5}>
-            <a style={style}></a>
-        </Badge>
-        <Badge dot>
-            <a style={style}></a>
-        </Badge>
-        <Badge count={5} />
-        <Badge dot />
-    </div>
-));
+export const Default = () => (
+  <div>
+    <Badge count={5}>
+      <a style={style}></a>
+    </Badge>
+    <Badge dot>
+      <a style={style}></a>
+    </Badge>
+    <Badge count={5} />
+    <Badge dot />
+  </div>
+);
 
-stories.add('Badge maxCount', () => (
-    <div>
-        <Badge count={99} >
-            <a style={style}></a>
-        </Badge>
-        <Badge count={100} >
-            <a style={style}></a>
-        </Badge>
-        <Badge count={99} overflowCount={10} >
-            <a style={style}></a>
-        </Badge>
-        <Badge count={1000} overflowCount={999} >
-            <a style={style}></a>
-        </Badge>
-    </div>
-));
+export const MaxCount = () => (
+  <div>
+    <Badge count={99}>
+      <a style={style}></a>
+    </Badge>
+    <Badge count={100}>
+      <a style={style}></a>
+    </Badge>
+    <Badge count={99} overflowCount={10}>
+      <a style={style}></a>
+    </Badge>
+    <Badge count={1000} overflowCount={999}>
+      <a style={style}></a>
+    </Badge>
+  </div>
+);
 
-stories.add('Badge type', () => (
-    <div>
-        <Badge count={5} type='primary' >
-            <a style={style}></a>
-        </Badge>
-        <Badge count={5} type='secondary' >
-            <a style={style}></a>
-        </Badge>
-        <Badge count={5} type='tertiary' >
-            <a style={style}></a>
-        </Badge>
-        <Badge count={5} type='warning' >
-            <a style={style}></a>
-        </Badge>
-        <Badge count={5} type='danger' >
-            <a style={style}></a>
-        </Badge>
-        <Badge dot type='primary' >
-            <a style={style}></a>
-        </Badge>
-    </div>
-));
+export const Type = () => (
+  <div>
+    <Badge count={5} type="primary">
+      <a style={style}></a>
+    </Badge>
+    <Badge count={5} type="secondary">
+      <a style={style}></a>
+    </Badge>
+    <Badge count={5} type="tertiary">
+      <a style={style}></a>
+    </Badge>
+    <Badge count={5} type="warning">
+      <a style={style}></a>
+    </Badge>
+    <Badge count={5} type="danger">
+      <a style={style}></a>
+    </Badge>
+    <Badge dot type="primary">
+      <a style={style}></a>
+    </Badge>
+  </div>
+);
 
-stories.add('Badge theme', () => (
-    <div>
-        <Badge count={5} theme='solid' >
-            <a style={style}></a>
-        </Badge>
-        <Badge count={5} theme='light' >
-            <a style={style}></a>
-        </Badge>
-        <Badge count={5} theme='inverted' >
-            <a style={style}></a>
-        </Badge>
-        <Badge dot theme='solid' >
-            <a style={style}></a>
-        </Badge>
-        <Badge dot theme='light' >
-            <a style={style}></a>
-        </Badge>
-        <Badge dot theme='inverted' >
-            <a style={style}></a>
-        </Badge>
-    </div>
-));
+export const Theme = () => (
+  <div>
+    <Badge count={5} theme="solid">
+      <a style={style}></a>
+    </Badge>
+    <Badge count={5} theme="light">
+      <a style={style}></a>
+    </Badge>
+    <Badge count={5} theme="inverted">
+      <a style={style}></a>
+    </Badge>
+    <Badge dot theme="solid">
+      <a style={style}></a>
+    </Badge>
+    <Badge dot theme="light">
+      <a style={style}></a>
+    </Badge>
+    <Badge dot theme="inverted">
+      <a style={style}></a>
+    </Badge>
+  </div>
+);

+ 34 - 37
packages/semi-ui/banner/_story/banner.stories.js

@@ -1,48 +1,45 @@
 import React from 'react';
-import { storiesOf } from '@storybook/react';
-// import { withKnobs, text, boolean } from '@storybook/addon-knobs';
-import withPropsCombinations from 'react-storybook-addon-props-combinations';
 
 import Banner from '../index';
-
 import Button from '@douyinfe/semi-ui/button/index';
 
-const stories = storiesOf('Banner', module);
-
-// stories.addDecorator(withKnobs);;
+export default {
+  title: 'Banner',
+}
 
-stories.add('basic banner', () => (
-    <>
-        <Banner description="A pre-released version is available" />
-        <br />
-        <Banner
-            onClick={e => console.log('clicking banner!!!!', e.target)}
-            onClose={e => {
-                e.stopPropagation();
-            }}
-            description="A pre-released version is available A pre-released version is availableA pre-released version is availableA pre-released version is availableA pre-released version is availableA pre-released version is availableA pre-released version is available"
-        >
-            <Button onClick={e => e.stopPropagation()}>test</Button>
-        </Banner>
-    </>
-));
 
-stories.add('in container', () => (
+export const Default = () => (
+  <>
+    <Banner description="A pre-released version is available" />
+    <br />
     <Banner
-        onClick={e => console.log('clicking banner!!!!', e.target)}
-        onClose={e => {
-            e.stopPropagation();
-        }}
-        fullMode={false}
-        title="标题"
-        description="A pre-released version is available"
+      onClick={e => console.log('clicking banner!!!!', e.target)}
+      onClose={e => {
+        e.stopPropagation();
+      }}
+      description="A pre-released version is available A pre-released version is availableA pre-released version is availableA pre-released version is availableA pre-released version is availableA pre-released version is availableA pre-released version is available"
     >
-        <Button onClick={e => e.stopPropagation()}>test</Button>
+      <Button onClick={e => e.stopPropagation()}>test</Button>
     </Banner>
-));
+  </>
+);
 
-stories.add('in container and bordered', () => (
-    <Banner title="标题" bordered description="A pre-released version is available">
-        <Button onClick={e => e.stopPropagation()}>test</Button>
-    </Banner>
-));
+export const InContainer = () => (
+  <Banner
+    onClick={e => console.log('clicking banner!!!!', e.target)}
+    onClose={e => {
+      e.stopPropagation();
+    }}
+    fullMode={false}
+    title="标题"
+    description="A pre-released version is available"
+  >
+    <Button onClick={e => e.stopPropagation()}>test</Button>
+  </Banner>
+);
+
+export const InContainerAndBordered = () => (
+  <Banner title="标题" bordered description="A pre-released version is available">
+    <Button onClick={e => e.stopPropagation()}>test</Button>
+  </Banner>
+);

+ 306 - 272
packages/semi-ui/breadcrumb/_story/breadcrumb.stories.js

@@ -1,283 +1,317 @@
 /* argus-disable unPkgSensitiveInfo */
 import React from 'react';
-import { storiesOf } from '@storybook/react';
 import Breadcrumb from '../index';
 import Popover from '../../popover';
-import { IconMore, IconArrowRight, IconHome, IconArticle, IconChevronRight, IconArticle } from '@douyinfe/semi-icons';
+import {
+  IconMore,
+  IconArrowRight,
+  IconHome,
+  IconArticle,
+  IconChevronRight,
+} from '@douyinfe/semi-icons';
 
-const stories = storiesOf('Breadcrumb', module);
-stories.add('regular breadcrumb', () => (
-    <div>
-        <Breadcrumb
-            routes={[
-                {
-                    path: '/home',
-                    name: 'home',
-                },
-                'breadcrumb',
-                'default',
-            ]}
-            onClick={item => console.log(item)}
-        />
-        <Breadcrumb
-            routes={[
-                {
-                    path: '/home',
-                    icon: <IconHome />,
-                    href: '#',
-                },
-                {
-                    path: '/breadcrumb',
-                    name: 'breadcrumb',
-                    icon: <IconChevronRight />,
-                },
-                'icon',
-            ]}
-            onClick={item => console.log(item)}
-        />
-        <Breadcrumb
-            routes={[
-                {
-                    path: '/home',
-                    name: 'home',
-                },
-                'breadcrumb',
-                'separator',
-                'string',
-            ]}
-            onClick={item => console.log(item)}
-            separator={'>'}
-        />
-        <Breadcrumb
-            routes={[
-                {
-                    path: '/home',
-                    name: 'home',
-                },
-                'breadcrumb',
-                'separator',
-                'with icon',
-            ]}
-            onClick={item => console.log(item)}
-            separator={<IconArrowRight size={'small'} />}
-        />
-        <Breadcrumb routes={['首页', '当这个页面标题很长时需要省略', '详情页']} onClick={item => console.log(item)} />
-        <Breadcrumb
-            routes={['首页', '当层级很多的时候', '又一层很长需要省略的时候', '再一层', '上上一层', '上一层', '详情页']}
-            onClick={item => console.log(item)}
-        />
-    </div>
-));
-stories.add('compact breadcrumb', () => (
-    <div>
-        <Breadcrumb
-            routes={[
-                {
-                    path: '/home',
-                    name: 'home',
-                },
-                'breadcrumb',
-                'compact',
-            ]}
-            onClick={item => console.log(item)}
-            compact={true}
-        />
-        <Breadcrumb
-            routes={[
-                {
-                    path: '/home',
-                    icon: <IconHome />,
-                },
-                {
-                    path: '/breadcrumb',
-                    name: 'breadcrumb',
-                    icon: <IconChevronRight />,
-                },
-                'icon',
-            ]}
-            onClick={item => console.log(item)}
-            compact={true}
-        />
-        <Breadcrumb
-            routes={[
-                {
-                    path: '/home',
-                    name: 'home',
-                },
-                'breadcrumb',
-                'separator',
-                'string',
-            ]}
-            onClick={item => console.log(item)}
-            separator={'>'}
-            compact={true}
-        />
-        <Breadcrumb
-            routes={[
-                {
-                    path: '/home',
-                    name: 'home',
-                },
-                'breadcrumb',
-                'separator',
-                'icon',
-            ]}
-            onClick={item => console.log(item)}
-            separator={<IconArrowRight size={'small'} />}
-            compact={true}
-        />
-        <Breadcrumb
-            routes={['首页', '当这个页面标题很长时需要省略', '详情页']}
-            onClick={item => console.log(item)}
-            compact={true}
-        />
-        <Breadcrumb
-            routes={['首页', '当层级很多的时候', '又一层很长需要省略的时候', '再一层', '上上一层', '上一层', '详情页']}
-            onClick={item => console.log(item)}
-            compact={true}
-        />
-    </div>
-));
-stories.add('breadcrumbitem', () => (
-    <div>
-        <Breadcrumb onClick={item => console.log(item)}>
-            <Breadcrumb.Item onClick={item => console.log('child', item)}>home</Breadcrumb.Item>
-            <Breadcrumb.Item href="#">breadcrumb</Breadcrumb.Item>
-            <Breadcrumb.Item>default</Breadcrumb.Item>
-        </Breadcrumb>
-        <Breadcrumb onClick={item => console.log(item)}>
-            <Breadcrumb.Item icon={<IconHome />}></Breadcrumb.Item>
-            <Breadcrumb.Item>breadcrumb</Breadcrumb.Item>
-            <Breadcrumb.Item>default</Breadcrumb.Item>
-        </Breadcrumb>
-        <Breadcrumb separator={'>'} onClick={item => console.log(item)}>
-            <Breadcrumb.Item>home</Breadcrumb.Item>
-            <Breadcrumb.Item href="#">breadcrumb</Breadcrumb.Item>
-            <Breadcrumb.Item>separator</Breadcrumb.Item>
-        </Breadcrumb>
-        <Breadcrumb compact={true} onClick={item => console.log(item)}>
-            <Breadcrumb.Item>home</Breadcrumb.Item>
-            <Breadcrumb.Item>breadcrumb</Breadcrumb.Item>
-            <Breadcrumb.Item>compact</Breadcrumb.Item>
-        </Breadcrumb>
-        <Breadcrumb onClick={item => console.log(item)}>
-            <Breadcrumb.Item>首页</Breadcrumb.Item>
-            <Breadcrumb.Item>当这个页面标题很长时需要省略</Breadcrumb.Item>
-            <Breadcrumb.Item>详情页</Breadcrumb.Item>
-        </Breadcrumb>
-        <Breadcrumb onClick={item => console.log(item)}>
-            <Breadcrumb.Item>首页</Breadcrumb.Item>
-            <Breadcrumb.Item>当层级很多的时候</Breadcrumb.Item>
-            <Breadcrumb.Item>又一层很长需要省略的时候</Breadcrumb.Item>
-            <Breadcrumb.Item>再一层</Breadcrumb.Item>
-            <Breadcrumb.Item>上上一层</Breadcrumb.Item>
-            <Breadcrumb.Item>上一层</Breadcrumb.Item>
-            <Breadcrumb.Item>详情页</Breadcrumb.Item>
-        </Breadcrumb>
-        <Breadcrumb></Breadcrumb>
-    </div>
-));
-stories.add('test', () => (
-    <div>
-        <Breadcrumb onClick={item => console.log(item)}>
-            <Breadcrumb.Item onClick={item => console.log('child', item)}>home jump</Breadcrumb.Item>
-            <Breadcrumb.Item href="#">breadcrumb</Breadcrumb.Item>
-            <Breadcrumb.Item>
-                <h1>default</h1>
-            </Breadcrumb.Item>
-        </Breadcrumb>
-        <Breadcrumb>
-            <Breadcrumb.Item icon={<IconHome />}></Breadcrumb.Item>
-            <Breadcrumb.Item icon={<IconArticle />}>
-                <h5>breadcrumb</h5>
-            </Breadcrumb.Item>
-            <Breadcrumb.Item>with icon</Breadcrumb.Item>
-        </Breadcrumb>
-    </div>
-));
-const serpator = '-'; // 用于拼接 restItem 数组项的分隔符
+export default {
+  title: 'Breadcrumb',
+}
+
+export const Default = () => (
+  <div>
+    <Breadcrumb
+      routes={[
+        {
+          path: '/home',
+          name: 'home',
+        },
+        'breadcrumb',
+        'default',
+      ]}
+      onClick={item => console.log(item)}
+    />
+    <Breadcrumb
+      routes={[
+        {
+          path: '/home',
+          icon: <IconHome />,
+          href: '#',
+        },
+        {
+          path: '/breadcrumb',
+          name: 'breadcrumb',
+          icon: <IconChevronRight />,
+        },
+        'icon',
+      ]}
+      onClick={item => console.log(item)}
+    />
+    <Breadcrumb
+      routes={[
+        {
+          path: '/home',
+          name: 'home',
+        },
+        'breadcrumb',
+        'separator',
+        'string',
+      ]}
+      onClick={item => console.log(item)}
+      separator={'>'}
+    />
+    <Breadcrumb
+      routes={[
+        {
+          path: '/home',
+          name: 'home',
+        },
+        'breadcrumb',
+        'separator',
+        'with icon',
+      ]}
+      onClick={item => console.log(item)}
+      separator={<IconArrowRight size={'small'} />}
+    />
+    <Breadcrumb
+      routes={['首页', '当这个页面标题很长时需要省略', '详情页']}
+      onClick={item => console.log(item)}
+    />
+    <Breadcrumb
+      routes={[
+        '首页',
+        '当层级很多的时候',
+        '又一层很长需要省略的时候',
+        '再一层',
+        '上上一层',
+        '上一层',
+        '详情页',
+      ]}
+      onClick={item => console.log(item)}
+    />
+  </div>
+);
+
+export const Compact = () => (
+  <div>
+    <Breadcrumb
+      routes={[
+        {
+          path: '/home',
+          name: 'home',
+        },
+        'breadcrumb',
+        'compact',
+      ]}
+      onClick={item => console.log(item)}
+      compact={true}
+    />
+    <Breadcrumb
+      routes={[
+        {
+          path: '/home',
+          icon: <IconHome />,
+        },
+        {
+          path: '/breadcrumb',
+          name: 'breadcrumb',
+          icon: <IconChevronRight />,
+        },
+        'icon',
+      ]}
+      onClick={item => console.log(item)}
+      compact={true}
+    />
+    <Breadcrumb
+      routes={[
+        {
+          path: '/home',
+          name: 'home',
+        },
+        'breadcrumb',
+        'separator',
+        'string',
+      ]}
+      onClick={item => console.log(item)}
+      separator={'>'}
+      compact={true}
+    />
+    <Breadcrumb
+      routes={[
+        {
+          path: '/home',
+          name: 'home',
+        },
+        'breadcrumb',
+        'separator',
+        'icon',
+      ]}
+      onClick={item => console.log(item)}
+      separator={<IconArrowRight size={'small'} />}
+      compact={true}
+    />
+    <Breadcrumb
+      routes={['首页', '当这个页面标题很长时需要省略', '详情页']}
+      onClick={item => console.log(item)}
+      compact={true}
+    />
+    <Breadcrumb
+      routes={[
+        '首页',
+        '当层级很多的时候',
+        '又一层很长需要省略的时候',
+        '再一层',
+        '上上一层',
+        '上一层',
+        '详情页',
+      ]}
+      onClick={item => console.log(item)}
+      compact={true}
+    />
+  </div>
+);
+
+export const BreadcrumbItemJSX = () => (
+  <div>
+    <Breadcrumb onClick={item => console.log(item)}>
+      <Breadcrumb.Item onClick={item => console.log('child', item)}>home</Breadcrumb.Item>
+      <Breadcrumb.Item href="#">breadcrumb</Breadcrumb.Item>
+      <Breadcrumb.Item>default</Breadcrumb.Item>
+    </Breadcrumb>
+    <Breadcrumb onClick={item => console.log(item)}>
+      <Breadcrumb.Item icon={<IconHome />}></Breadcrumb.Item>
+      <Breadcrumb.Item>breadcrumb</Breadcrumb.Item>
+      <Breadcrumb.Item>default</Breadcrumb.Item>
+    </Breadcrumb>
+    <Breadcrumb separator={'>'} onClick={item => console.log(item)}>
+      <Breadcrumb.Item>home</Breadcrumb.Item>
+      <Breadcrumb.Item href="#">breadcrumb</Breadcrumb.Item>
+      <Breadcrumb.Item>separator</Breadcrumb.Item>
+    </Breadcrumb>
+    <Breadcrumb compact={true} onClick={item => console.log(item)}>
+      <Breadcrumb.Item>home</Breadcrumb.Item>
+      <Breadcrumb.Item>breadcrumb</Breadcrumb.Item>
+      <Breadcrumb.Item>compact</Breadcrumb.Item>
+    </Breadcrumb>
+    <Breadcrumb onClick={item => console.log(item)}>
+      <Breadcrumb.Item>首页</Breadcrumb.Item>
+      <Breadcrumb.Item>当这个页面标题很长时需要省略</Breadcrumb.Item>
+      <Breadcrumb.Item>详情页</Breadcrumb.Item>
+    </Breadcrumb>
+    <Breadcrumb onClick={item => console.log(item)}>
+      <Breadcrumb.Item>首页</Breadcrumb.Item>
+      <Breadcrumb.Item>当层级很多的时候</Breadcrumb.Item>
+      <Breadcrumb.Item>又一层很长需要省略的时候</Breadcrumb.Item>
+      <Breadcrumb.Item>再一层</Breadcrumb.Item>
+      <Breadcrumb.Item>上上一层</Breadcrumb.Item>
+      <Breadcrumb.Item>上一层</Breadcrumb.Item>
+      <Breadcrumb.Item>详情页</Breadcrumb.Item>
+    </Breadcrumb>
+    <Breadcrumb></Breadcrumb>
+  </div>
+);
+
+export const Test = () => (
+  <div>
+    <Breadcrumb onClick={item => console.log(item)}>
+      <Breadcrumb.Item onClick={item => console.log('child', item)}>home jump</Breadcrumb.Item>
+      <Breadcrumb.Item href="#">breadcrumb</Breadcrumb.Item>
+      <Breadcrumb.Item>
+        <h1>default</h1>
+      </Breadcrumb.Item>
+    </Breadcrumb>
+    <Breadcrumb>
+      <Breadcrumb.Item icon={<IconHome />}></Breadcrumb.Item>
+      <Breadcrumb.Item icon={<IconArticle />}>
+        <h5>breadcrumb</h5>
+      </Breadcrumb.Item>
+      <Breadcrumb.Item>with icon</Breadcrumb.Item>
+    </Breadcrumb>
+  </div>
+);
+
+const separator = '-'; // 用于拼接 restItem 数组项的分隔符
 
 const renderMore = restItem => {
-    const content = (
-        <>
-            {restItem.map((item, idx) => (
-                <React.Fragment key={`restItem-${idx}`}>
-                    {item}
-                    {idx !== restItem.length - 1 && (
-                        <span
-                            style={{
-                                color: 'var(--semi-color-text-2)',
-                                marginRight: '6px',
-                            }}
-                        >
-                            {serpator}
-                        </span>
-                    )}
-                </React.Fragment>
-            ))}
-        </>
-    );
-    return (
-        <Popover
-            content={content}
-            style={{
-                padding: 12,
-            }}
-            showArrow
-        >
-            <IconMore />
-        </Popover>
-    );
+  const content = (
+    <>
+      {restItem.map((item, idx) => (
+        <React.Fragment key={`restItem-${idx}`}>
+          {item}
+          {idx !== restItem.length - 1 && (
+            <span
+              style={{
+                color: 'var(--semi-color-text-2)',
+                marginRight: '6px',
+              }}
+            >
+              {separator}
+            </span>
+          )}
+        </React.Fragment>
+      ))}
+    </>
+  );
+  return (
+    <Popover
+      content={content}
+      style={{
+        padding: 12,
+      }}
+      showArrow
+    >
+      <IconMore />
+    </Popover>
+  );
 };
 
-stories.add('renderMore', () => (
-    <div
-        style={{
-            margin: '100px',
-        }}
+export const RenderMore = () => (
+  <div
+    style={{
+      margin: '100px',
+    }}
+  >
+    <Breadcrumb
+      renderMore={restItem => renderMore(restItem)}
+      onClick={(item, e) => console.log(item, e)}
     >
-        <Breadcrumb renderMore={restItem => renderMore(restItem)} onClick={(item, e) => console.log(item, e)}>
-            <Breadcrumb.Item>首页</Breadcrumb.Item>
-            <Breadcrumb.Item>当层级很多的时候</Breadcrumb.Item>
-            <Breadcrumb.Item>又一层</Breadcrumb.Item>
-            <Breadcrumb.Item>再一层</Breadcrumb.Item>
-            <Breadcrumb.Item>上上一层</Breadcrumb.Item>
-            <Breadcrumb.Item>上一层</Breadcrumb.Item>
-            <Breadcrumb.Item>详情页</Breadcrumb.Item>
-        </Breadcrumb>
-        <br />
-        <br />
-        <div>
-            <Breadcrumb
-                renderMore={restItem => renderMore(restItem)}
-                onClick={(item, e) => console.log(item, e)}
-                routes={[
-                    {
-                        path: '/',
-                        href: '/',
-                        icon: <IconHome />,
-                    },
-                    {
-                        path: '/breadcrumb',
-                        href: '/components/breadcrumb',
-                        name: 'breadcrumb',
-                        icon: <IconArticle />,
-                    },
-                    {
-                        path: '/breadcrumb',
-                        href: '/components/breadcrumb',
-                        name: 'breadcrumb',
-                        icon: <IconArticle />,
-                    },
-                    {
-                        path: '/breadcrumb',
-                        href: '/components/breadcrumb',
-                        name: 'breadcrumb',
-                        icon: <IconArticle />,
-                    },
-                    'with icon',
-                ]}
-            />
-        </div>
+      <Breadcrumb.Item>首页</Breadcrumb.Item>
+      <Breadcrumb.Item>当层级很多的时候</Breadcrumb.Item>
+      <Breadcrumb.Item>又一层</Breadcrumb.Item>
+      <Breadcrumb.Item>再一层</Breadcrumb.Item>
+      <Breadcrumb.Item>上上一层</Breadcrumb.Item>
+      <Breadcrumb.Item>上一层</Breadcrumb.Item>
+      <Breadcrumb.Item>详情页</Breadcrumb.Item>
+    </Breadcrumb>
+    <br />
+    <br />
+    <div>
+      <Breadcrumb
+        renderMore={restItem => renderMore(restItem)}
+        onClick={(item, e) => console.log(item, e)}
+        routes={[
+          {
+            path: '/',
+            href: '/',
+            icon: <IconHome />,
+          },
+          {
+            path: '/breadcrumb',
+            href: '/components/breadcrumb',
+            name: 'breadcrumb',
+            icon: <IconArticle />,
+          },
+          {
+            path: '/breadcrumb',
+            href: '/components/breadcrumb',
+            name: 'breadcrumb',
+            icon: <IconArticle />,
+          },
+          {
+            path: '/breadcrumb',
+            href: '/components/breadcrumb',
+            name: 'breadcrumb',
+            icon: <IconArticle />,
+          },
+          'with icon',
+        ]}
+      />
     </div>
-));
+  </div>
+);

+ 265 - 239
packages/semi-ui/button/_story/button.stories.js

@@ -1,5 +1,4 @@
 import React, { useState } from 'react';
-import { storiesOf } from '@storybook/react'; // import { withKnobs, text, boolean } from '@storybook/addon-knobs';
 
 import withPropsCombinations from 'react-storybook-addon-props-combinations';
 import { strings, numbers, cssClasses } from '@douyinfe/semi-foundation/button/constants';
@@ -8,247 +7,274 @@ import ButtonGroup from '../buttonGroup';
 import SplitButtonGroup from '../splitButtonGroup';
 import Dropdown from '../../dropdown';
 import { Tooltip, Switch } from '@douyinfe/semi-ui';
-import { IconTick, IconEdit, IconTwitter, IconUser,IconCopy,IconSearch,IconPlay } from '@douyinfe/semi-icons';
+import {
+  IconTick,
+  IconEdit,
+  IconTwitter,
+  IconUser,
+  IconCopy,
+  IconSearch,
+  IconPlay,
+} from '@douyinfe/semi-icons';
 import Collapse from '../../collapse';
 
-const stories = storiesOf('Button', module); // stories.addDecorator(withKnobs);;
-
-stories.add('button', () => <Button type="primary">UI semi</Button>);
-stories.add('danger', () => <Button type="danger">hello button</Button>);
-stories.add('warning', () => <Button type="warning">hello button</Button>);
-stories.add('with icon', () => (
-    <>
-        <Button icon={<IconTick />}>hello button</Button>
-        <br />
-        <Button icon={<IconEdit />} noHorizontalPadding={false} ghost={false}>
-            Edit me
-        </Button>
-        <Button icon={<IconUser />} />
-    </>
-));
-stories.add(
-    'combination show',
-    withPropsCombinations(
-        Button,
-        {
-            disabled: [false, true],
-            children: ['hello button'],
-            size: strings.sizes,
-            type: strings.btnTypes,
-            theme: strings.themes, // block: [false, true],
-            // ghost: [false, true],
-            // light: [false, true],
-        },
-        {
-            showSource: false,
-        }
-    )
+export default {
+  title: 'Button',
+}
+
+export const Primary = () => <Button type="primary">UI semi</Button>;
+
+export const Danger = () => <Button type="danger">hello button</Button>;
+
+export const Warning = () => <Button type="warning">hello button</Button>;
+
+export const WithIcon = () => (
+  <>
+    <Button icon={<IconTick />}>hello button</Button>
+    <br />
+    <Button icon={<IconEdit />} noHorizontalPadding={false} ghost={false}>
+      Edit me
+    </Button>
+    <Button icon={<IconUser />} />
+  </>
 );
-stories.add('button group', () => (
-    <div>
-        <ButtonGroup disabled>
-            <Button>复制</Button>
-            <Button type="primary">查找</Button>
-            <Button type="danger">粘贴</Button>
-        </ButtonGroup>
-        <br />
-        <ButtonGroup>
-            <Button icon={<IconCopy />} theme={'solid'} />
-            <Button icon={<IconSearch />} theme={'solid'} />
-            <Button icon={<IconPlay />} theme={'solid'} />
-        </ButtonGroup>
-        <br />
-
-        <ButtonGroup size={'large'}>
-            <Button icon={<IconCopy />} theme={'solid'} />
-            <Button icon={<IconSearch />} theme={'solid'} />
-            <Button icon={<IconPlay />} theme={'solid'} />
-        </ButtonGroup>
-        <br />
-
-        <ButtonGroup size={'small'}>
-            <Button icon={<IconCopy />} theme={'solid'} />
-            <Button icon={<IconSearch />} theme={'solid'} />
-            <Button icon={<IconPlay />} theme={'solid'} />
-        </ButtonGroup>
-        <br />
-
-        <ButtonGroup>
-            <Button icon={<IconCopy />} theme={'solid'}>
-                拷贝
-            </Button>
-            <Button icon={<IconSearch />} theme={'solid'}>
-                搜索
-            </Button>
-            <Button icon={<IconPlay />} theme={'solid'}>
-                播放
-            </Button>
-        </ButtonGroup>
-        <br />
-
-        <ButtonGroup size={'large'}>
-            <Button icon={<IconCopy />} theme={'solid'}>
-                拷贝
-            </Button>
-            <Button icon={<IconSearch />} theme={'solid'}>
-                搜索
-            </Button>
-            <Button icon={<IconPlay />} theme={'solid'}>
-                播放
-            </Button>
-        </ButtonGroup>
-        <br />
-
-        <ButtonGroup size={'small'}>
-            <Button icon={<IconCopy />} theme={'solid'}>
-                拷贝
-            </Button>
-            <Button icon={<IconSearch />} theme={'solid'}>
-                搜索
-            </Button>
-            <Button icon={<IconPlay />} theme={'solid'}>
-                播放
-            </Button>
-        </ButtonGroup>
-        <br />
-    </div>
-));
-stories.add('button loading', () => {
-    function LoadingDemo() {
-        const [loading, setLoading] = useState(false);
-        return (
-            <div
-                style={{
-                    maxWidth: 400,
-                    maxHeight: 300,
-                    padding: 50,
-                }}
-            >
-                <div>
-                    <Switch checked={loading} onChange={loading => setLoading(loading)} />
-                </div>
-                <Button loading={loading}>保存</Button>
-                <Button loading={loading} type="danger" theme="solid">
-                    删除
-                </Button>
-                <Button loading={loading} type="danger" theme="solid" disabled>
-                    删除
-                </Button>
-                <Button loading={loading} type="danger" theme="solid" block>
-                    删除
-                </Button>
-                <Tooltip content={loading ? '正在保存' : '保存'}>
-                    <Button loading={loading}>保存</Button>
-                </Tooltip>
-                <Button icon={<IconEdit />} loading={loading} />
-                <Tooltip content={loading ? '载入中' : '编辑'}>
-                    <Button icon={<IconEdit />} loading={loading} />
-                </Tooltip>
-                <Tooltip content={loading ? '载入中' : '编辑'}>
-                    <Button icon={<IconEdit />} loading={loading} theme="solid" />
-                </Tooltip>
-                <Tooltip content={loading ? '载入中' : '编辑'}>
-                    <Button icon={<IconEdit />} loading={loading} theme="solid" type="danger" />
-                </Tooltip>
-                <Tooltip content={loading ? '载入中' : '编辑'}>
-                    <Button icon={<IconEdit />} loading={loading} theme="solid" type="warning" disabled />
-                </Tooltip>
-            </div>
-        );
-    }
-
-    return <LoadingDemo />;
-});
+
+export const CombinationShow = withPropsCombinations(
+  Button,
+  {
+    disabled: [false, true],
+    children: ['hello button'],
+    size: strings.sizes,
+    type: strings.btnTypes,
+    theme: strings.themes, // block: [false, true],
+    // ghost: [false, true],
+    // light: [false, true],
+  },
+  {
+    showSource: false,
+  }
+);
+
+export const ButtonGroupDemo = () => (
+  <div>
+    <ButtonGroup disabled>
+      <Button>复制</Button>
+      <Button type="primary">查找</Button>
+      <Button type="danger">粘贴</Button>
+    </ButtonGroup>
+    <br />
+    <ButtonGroup>
+      <Button icon={<IconCopy />} theme={'solid'} />
+      <Button icon={<IconSearch />} theme={'solid'} />
+      <Button icon={<IconPlay />} theme={'solid'} />
+    </ButtonGroup>
+    <br />
+
+    <ButtonGroup size={'large'}>
+      <Button icon={<IconCopy />} theme={'solid'} />
+      <Button icon={<IconSearch />} theme={'solid'} />
+      <Button icon={<IconPlay />} theme={'solid'} />
+    </ButtonGroup>
+    <br />
+
+    <ButtonGroup size={'small'}>
+      <Button icon={<IconCopy />} theme={'solid'} />
+      <Button icon={<IconSearch />} theme={'solid'} />
+      <Button icon={<IconPlay />} theme={'solid'} />
+    </ButtonGroup>
+    <br />
+
+    <ButtonGroup>
+      <Button icon={<IconCopy />} theme={'solid'}>
+        拷贝
+      </Button>
+      <Button icon={<IconSearch />} theme={'solid'}>
+        搜索
+      </Button>
+      <Button icon={<IconPlay />} theme={'solid'}>
+        播放
+      </Button>
+    </ButtonGroup>
+    <br />
+
+    <ButtonGroup size={'large'}>
+      <Button icon={<IconCopy />} theme={'solid'}>
+        拷贝
+      </Button>
+      <Button icon={<IconSearch />} theme={'solid'}>
+        搜索
+      </Button>
+      <Button icon={<IconPlay />} theme={'solid'}>
+        播放
+      </Button>
+    </ButtonGroup>
+    <br />
+
+    <ButtonGroup size={'small'}>
+      <Button icon={<IconCopy />} theme={'solid'}>
+        拷贝
+      </Button>
+      <Button icon={<IconSearch />} theme={'solid'}>
+        搜索
+      </Button>
+      <Button icon={<IconPlay />} theme={'solid'}>
+        播放
+      </Button>
+    </ButtonGroup>
+    <br />
+  </div>
+);
+
+export function Loading() {
+    const [loading, setLoading] = useState(false);
+    return (
+      <div
+        style={{
+          maxWidth: 400,
+          maxHeight: 300,
+          padding: 50,
+        }}
+      >
+        <div>
+          <Switch checked={loading} onChange={loading => setLoading(loading)} />
+        </div>
+        <Button loading={loading}>保存</Button>
+        <Button loading={loading} type="danger" theme="solid">
+          删除
+        </Button>
+        <Button loading={loading} type="danger" theme="solid" disabled>
+          删除
+        </Button>
+        <Button loading={loading} type="danger" theme="solid" block>
+          删除
+        </Button>
+        <Tooltip content={loading ? '正在保存' : '保存'}>
+          <Button loading={loading}>保存</Button>
+        </Tooltip>
+        <Button icon={<IconEdit />} loading={loading} />
+        <Tooltip content={loading ? '载入中' : '编辑'}>
+          <Button icon={<IconEdit />} loading={loading} />
+        </Tooltip>
+        <Tooltip content={loading ? '载入中' : '编辑'}>
+          <Button icon={<IconEdit />} loading={loading} theme="solid" />
+        </Tooltip>
+        <Tooltip content={loading ? '载入中' : '编辑'}>
+          <Button icon={<IconEdit />} loading={loading} theme="solid" type="danger" />
+        </Tooltip>
+        <Tooltip content={loading ? '载入中' : '编辑'}>
+          <Button icon={<IconEdit />} loading={loading} theme="solid" type="warning" disabled />
+        </Tooltip>
+      </div>
+    );
+};
+
 const menu = [
-    {
-        node: 'title',
-        name: '标题一',
-    },
-    {
-        node: 'item',
-        name: '编辑项目',
-        onClick: () => console.log('编辑项目点击'),
-    },
-    {
-        node: 'item',
-        name: '重置项目',
-        type: 'secondary',
-    },
-    {
-        node: 'divider',
-    },
-    {
-        node: 'item',
-        name: '从项目创建模版',
-        type: 'tertiary',
-    },
-    {
-        node: 'item',
-        name: '复制项目',
-        type: 'warning',
-    },
-    {
-        node: 'divider',
-    },
-    {
-        node: 'item',
-        name: '删除项目',
-        type: 'danger',
-    },
+  {
+    node: 'title',
+    name: '标题一',
+  },
+  {
+    node: 'item',
+    name: '编辑项目',
+    onClick: () => console.log('编辑项目点击'),
+  },
+  {
+    node: 'item',
+    name: '重置项目',
+    type: 'secondary',
+  },
+  {
+    node: 'divider',
+  },
+  {
+    node: 'item',
+    name: '从项目创建模版',
+    type: 'tertiary',
+  },
+  {
+    node: 'item',
+    name: '复制项目',
+    type: 'warning',
+  },
+  {
+    node: 'divider',
+  },
+  {
+    node: 'item',
+    name: '删除项目',
+    type: 'danger',
+  },
 ];
 const content = '批量通过';
-stories.add('split button', () => (
-    <>
-        <p>基础</p>
-        <SplitButtonGroup>
-            <Button theme="solid" type="primary">
-                前面
-            </Button>
-            <Button theme="solid" type="primary">
-                后面
-            </Button>
-        </SplitButtonGroup>
-        <br />
-        <SplitButtonGroup>
-            <Button theme="solid" type="primary">
-                One
-            </Button>
-        </SplitButtonGroup>
-        <br />
-        <SplitButtonGroup>
-            <Button size="small" theme="solid" type="primary">
-                前面
-            </Button>
-            <Button size="small" theme="solid" type="primary">
-                中间
-            </Button>
-            <Button size="small" theme="solid" type="primary">
-                后面
-            </Button>
-            <Dropdown trigger="click" menu={menu} position="bottomRight">
-                <Button size="small" theme="solid" type="primary" icon={<IconTwitter />}></Button>
-            </Dropdown>
-        </SplitButtonGroup>
-    </>
-));
-
-stories.add('button stopPropagation when disabled', () => (
-    <>
-        <Collapse>
-            <Collapse.Panel header={<>title<Button>按钮</Button></>} itemKey="1">
-                <p>Hi, bytedance dance dance. This is the docsite of Semi UI. </p>
-            </Collapse.Panel>
-            <Collapse.Panel header={<>title<Button disabled>按钮</Button></>} itemKey="2">
-                <p>Hi, bytedance dance dance. This is the docsite of Semi UI. </p>
-            </Collapse.Panel>
-        </Collapse>
-        <div onClick={() => console.log('div')}>
-            <span>正常冒泡</span>
-            <Button onClick={() => console.log('button')}>按钮</Button>
-        </div>
-        <div onClick={() => console.log('div')}>
-            <span>禁用 Button 后,阻止冒泡</span>
-            <Button disabled onClick={() => console.log('button')}>按钮</Button>
-        </div>
-    </>
-));
+
+export const SplitButton = () => (
+  <>
+    <p>基础</p>
+    <SplitButtonGroup>
+      <Button theme="solid" type="primary">
+        前面
+      </Button>
+      <Button theme="solid" type="primary">
+        后面
+      </Button>
+    </SplitButtonGroup>
+    <br />
+    <SplitButtonGroup>
+      <Button theme="solid" type="primary">
+        One
+      </Button>
+    </SplitButtonGroup>
+    <br />
+    <SplitButtonGroup>
+      <Button size="small" theme="solid" type="primary">
+        前面
+      </Button>
+      <Button size="small" theme="solid" type="primary">
+        中间
+      </Button>
+      <Button size="small" theme="solid" type="primary">
+        后面
+      </Button>
+      <Dropdown trigger="click" menu={menu} position="bottomRight">
+        <Button size="small" theme="solid" type="primary" icon={<IconTwitter />}></Button>
+      </Dropdown>
+    </SplitButtonGroup>
+  </>
+);
+
+export const StopPropagationWhenDisabled = () => (
+  <>
+    <Collapse>
+      <Collapse.Panel
+        header={
+          <>
+            title<Button>按钮</Button>
+          </>
+        }
+        itemKey="1"
+      >
+        <p>Hi, bytedance dance dance. This is the docsite of Semi UI. </p>
+      </Collapse.Panel>
+      <Collapse.Panel
+        header={
+          <>
+            title<Button disabled>按钮</Button>
+          </>
+        }
+        itemKey="2"
+      >
+        <p>Hi, bytedance dance dance. This is the docsite of Semi UI. </p>
+      </Collapse.Panel>
+    </Collapse>
+    <div onClick={() => console.log('div')}>
+      <span>正常冒泡</span>
+      <Button onClick={() => console.log('button')}>按钮</Button>
+    </div>
+    <div onClick={() => console.log('div')}>
+      <span>禁用 Button 后,阻止冒泡</span>
+      <Button disabled onClick={() => console.log('button')}>
+        按钮
+      </Button>
+    </div>
+  </>
+);

+ 345 - 343
packages/semi-ui/calendar/_story/calendar.stories.js

@@ -1,6 +1,4 @@
 import React, { useState } from 'react';
-import { storiesOf } from '@storybook/react';
-import withPropsCombinations from 'react-storybook-addon-props-combinations';
 
 import Calendar from '../index';
 import { Button, RadioGroup, Radio, LocaleProvider, Select } from '@douyinfe/semi-ui';
@@ -18,386 +16,390 @@ import th_TH from '@douyinfe/semi-ui/locale/source/th_TH';
 import tr_TR from '@douyinfe/semi-ui/locale/source/tr_TR';
 import pt_BR from '@douyinfe/semi-ui/locale/source/pt_BR';
 
-const stories = storiesOf('Calendar', module);
 const { Option } = Select;
 
-// stories.addDecorator(withKnobs);;
+export default {
+  title: 'Calendar',
+}
 
 const time = new Date();
 let id = 0;
 const language = {
-    'zh_CN': zh_CN,
-    'en_GB': en_GB,
-    'ko_KR': ko_KR,
-    'ja_JP': ja_JP,
-    'ar': ar,
-    'vi_VN': vi_VN,
-    'ru_RU': ru_RU,
-    'id_ID': id_ID,
-    'ms_MY': ms_MY,
-    'th_TH': th_TH,
-    'tr_TR': tr_TR,
-    'pt_BR': pt_BR,
+  zh_CN: zh_CN,
+  en_GB: en_GB,
+  ko_KR: ko_KR,
+  ja_JP: ja_JP,
+  ar: ar,
+  vi_VN: vi_VN,
+  ru_RU: ru_RU,
+  id_ID: id_ID,
+  ms_MY: ms_MY,
+  th_TH: th_TH,
+  tr_TR: tr_TR,
+  pt_BR: pt_BR,
 };
 
 const events = [
-    {
-        allDay: true,
-        children: (<div style={{ backgroundColor: 'blue', height: '100%' }}>today-allDay</div>)
-    },
-    {
-        start: time,
-        children: (<div style={{ backgroundColor: 'indigo', height: '100px' }}>today-now</div>)
-    },
-    {
-        allDay: true,
-        children: (<div style={{ backgroundColor: 'green', height: '100%' }}>today-allDay2</div>)
-    }, {
-        allDay: true,
-        children: (<div style={{ backgroundColor: 'blue', height: '100%' }}>today-allDay3</div>)
-    }, {
-        allDay: true,
-        children: (<div style={{ backgroundColor: 'green', height: '100%' }}>today-allDay4</div>)
-    },
+  {
+    allDay: true,
+    children: <div style={{ backgroundColor: 'blue', height: '100%' }}>today-allDay</div>,
+  },
+  {
+    start: time,
+    children: <div style={{ backgroundColor: 'indigo', height: '100px' }}>today-now</div>,
+  },
+  {
+    allDay: true,
+    children: <div style={{ backgroundColor: 'green', height: '100%' }}>today-allDay2</div>,
+  },
+  {
+    allDay: true,
+    children: <div style={{ backgroundColor: 'blue', height: '100%' }}>today-allDay3</div>,
+  },
+  {
+    allDay: true,
+    children: <div style={{ backgroundColor: 'green', height: '100%' }}>today-allDay4</div>,
+  },
 ];
 
 const weeklyEvents = [
-    {
-        allDay: true,
-        start: new Date(2019, 6, 15, 8, 0, 0),
-        children: (<div style={{ backgroundColor: 'blue', height: '100%' }}>7-15-AllDayA</div>)
-    },
-    {
-        start: new Date(2019, 6, 16, 8, 32, 0),
-        children: (<div style={{ backgroundColor: 'indigo', height: '100%' }}>7-16 8:32 here is a very long content just to see if the content will collapse or not not sure if this is long enough aaaaaaaaaaa</div>)
-    },
-    {
-        start: new Date(2019, 6, 16, 14, 30, 0),
-        end: new Date(2019, 6, 16, 20, 0, 0),
-        children: (<div style={{ backgroundColor: 'indigo', height: '100%' }}>7-16 14:30-20:00</div>)
-    },
-    {
-        start: new Date(2019, 6, 18, 14, 45, 0),
-        end: new Date(2019, 6, 19, 6, 18, 0),
-        children: (<div style={{ backgroundColor: 'indigo', height: '100%' }}>7-18 14:45 ~ 7-19 6:18</div>)
-    },
-    // {
-    //     start: new Date(2019, 6, 18, 8, 0, 0),
-    //     end: new Date(2019, 6, 20, 6, 0, 0),
-    //     children: (<div style={{backgroundColor: 'indigo', height: '100%'}}>AllDayB</div>)
-    // },
-    // {
-    //     start: new Date(2019, 6, 15, 9, 0, 0),
-    //     end: new Date(2019, 6, 16, 23, 0, 0),
-    //     children: (<div style={{backgroundColor: 'LightSkyBlue', height: '100%'}}>AllDayC</div>)
-    // },
-    // {
-    //     start: new Date(2019, 6, 14, 6, 0, 0),
-    //     end: new Date(2019, 6, 18, 6, 0, 0),
-    //     children: (<div style={{backgroundColor: 'YellowGreen', height: '100%'}}>AllDayD</div>)
-    // },
-    // {
-    //     start: new Date(2019, 6, 12, 20, 0, 0),
-    //     end: new Date(2019, 6, 16, 14, 0, 0),
-    //     children: (<div style={{backgroundColor: 'pink', height: '100%'}}>AllDayE</div>)
-    // },
-    // {
-    //     start: new Date(2019, 6, 19, 10, 0, 0),
-    //     end: new Date(2019, 6, 20, 16, 0, 0),
-    //     children: (<div style={{backgroundColor: 'red', height: '100%'}}>AllDayF</div>)
-    // },
-    // {
-    //     start: new Date(2019, 6, 11, 10, 0, 0),
-    //     end: new Date(2019, 6, 25, 8, 0, 0),
-    //     children: (<div style={{backgroundColor: 'green', height: '100%'}}>AllDayG</div>)
-    // },
-]
+  {
+    allDay: true,
+    start: new Date(2019, 6, 15, 8, 0, 0),
+    children: <div style={{ backgroundColor: 'blue', height: '100%' }}>7-15-AllDayA</div>,
+  },
+  {
+    start: new Date(2019, 6, 16, 8, 32, 0),
+    children: (
+      <div style={{ backgroundColor: 'indigo', height: '100%' }}>
+        7-16 8:32 here is a very long content just to see if the content will collapse or not not
+        sure if this is long enough aaaaaaaaaaa
+      </div>
+    ),
+  },
+  {
+    start: new Date(2019, 6, 16, 14, 30, 0),
+    end: new Date(2019, 6, 16, 20, 0, 0),
+    children: <div style={{ backgroundColor: 'indigo', height: '100%' }}>7-16 14:30-20:00</div>,
+  },
+  {
+    start: new Date(2019, 6, 18, 14, 45, 0),
+    end: new Date(2019, 6, 19, 6, 18, 0),
+    children: (
+      <div style={{ backgroundColor: 'indigo', height: '100%' }}>7-18 14:45 ~ 7-19 6:18</div>
+    ),
+  },
+];
 // const events = [];
 const date = new Date(2019, 6, 18, 8, 0, 0);
 
 const dailyEventStyle = {
-    borderRadius: '3px',
-    boxSizing: 'border-box',
-    border: 'var(--semi-color-primary) 1px solid',
-    padding: '10px',
-    backgroundColor: 'var(--semi-color-primary-light-default)',
-    height: '100%',
-    overflow: 'hidden'
+  borderRadius: '3px',
+  boxSizing: 'border-box',
+  border: 'var(--semi-color-primary) 1px solid',
+  padding: '10px',
+  backgroundColor: 'var(--semi-color-primary-light-default)',
+  height: '100%',
+  overflow: 'hidden',
 };
 const allDayStyle = {
-    borderRadius: '3px',
-    boxSizing: 'border-box',
-    border: 'var(--semi-color-bg-1) 1px solid',
-    marginRight: '12px',
-    padding: '2px 4px',
-    backgroundColor: 'var(--semi-color-primary-light-active)',
-    height: '100%',
-    overflow: 'hidden'
+  borderRadius: '3px',
+  boxSizing: 'border-box',
+  border: 'var(--semi-color-bg-1) 1px solid',
+  marginRight: '12px',
+  padding: '2px 4px',
+  backgroundColor: 'var(--semi-color-primary-light-active)',
+  height: '100%',
+  overflow: 'hidden',
 };
 
 const weeklyEvents2 = [
-    {
-        allDay: true,
-        start: new Date(2019, 6, 22, 8, 0, 0),
-        children: (<div style={{ backgroundColor: 'blue', height: '100%' }}>7-22-allDay</div>)
-    },
-    {
-        start: new Date(2019, 6, 23, 8, 32, 0),
-        children: (<div style={{ backgroundColor: 'indigo', height: '100%' }}>7-23 8:32</div>)
-    },
-    {
-        start: new Date(2019, 6, 23, 14, 30, 0),
-        end: new Date(2019, 6, 23, 20, 0, 0),
-        children: (<div style={{ backgroundColor: 'indigo', height: '100%' }}>7-23 14:30-20:00</div>)
-    },
-    {
-        start: new Date(2019, 6, 25, 14, 45, 0),
-        end: new Date(2019, 6, 26, 6, 18, 0),
-        children: (<div style={{ backgroundColor: 'indigo', height: '100%' }}>7-25 14:45 ~ 7-26 6:18</div>)
-    },
-    {
-        start: new Date(2019, 6, 25, 8, 0, 0),
-        end: new Date(2019, 6, 27, 6, 0, 0),
-        children: (<div style={{ backgroundColor: 'indigo', height: '100%' }}>7-25 8:00 ~ 7-27 6:00</div>)
-    },
-    {
-        start: new Date(2019, 6, 22, 9, 0, 0),
-        end: new Date(2019, 6, 23, 23, 0, 0),
-        children: (<div style={{ backgroundColor: 'LightSkyBlue', height: '100%' }}>7-22 9:00 ~ 7-23 23:00</div>)
-    },
-    {
-        start: new Date(2019, 6, 21, 6, 0, 0),
-        end: new Date(2019, 6, 25, 6, 0, 0),
-        children: (<div style={{ backgroundColor: 'YellowGreen', height: '100%' }}>7-21 6:00 ~ 7-25 6:00</div>)
-    },
-    {
-        start: new Date(2019, 6, 19, 20, 0, 0),
-        end: new Date(2019, 6, 23, 14, 0, 0),
-        children: (<div style={{ backgroundColor: 'pink', height: '100%' }}>7-19 20:00 ~ 7-23 14:00</div>)
-    },
-    {
-        start: new Date(2019, 6, 26, 10, 0, 0),
-        end: new Date(2019, 6, 27, 16, 0, 0),
-        children: (<div style={{ backgroundColor: 'red', height: '100%' }}>7-26 10:00 ~ 7-27 16:00</div>)
-    },
-    {
-        start: new Date(2019, 6, 18, 10, 0, 0),
-        end: new Date(2019, 6, 30, 8, 0, 0),
-        children: (<div style={{ backgroundColor: 'green', height: '100%' }}>7-18 10:00 ~ 7-30 8:00</div>)
-    },
-]
-
-stories.add('dayCalendar', () => {
-    return (
-        <div>
-            <Calendar
-                mode='day'
-                events={events}
-            // displayValue={new Date(2019, 6, 16, 8, 0, 0)}
-            ></Calendar>
-        </div>
-    );
-});
+  {
+    allDay: true,
+    start: new Date(2019, 6, 22, 8, 0, 0),
+    children: <div style={{ backgroundColor: 'blue', height: '100%' }}>7-22-allDay</div>,
+  },
+  {
+    start: new Date(2019, 6, 23, 8, 32, 0),
+    children: <div style={{ backgroundColor: 'indigo', height: '100%' }}>7-23 8:32</div>,
+  },
+  {
+    start: new Date(2019, 6, 23, 14, 30, 0),
+    end: new Date(2019, 6, 23, 20, 0, 0),
+    children: <div style={{ backgroundColor: 'indigo', height: '100%' }}>7-23 14:30-20:00</div>,
+  },
+  {
+    start: new Date(2019, 6, 25, 14, 45, 0),
+    end: new Date(2019, 6, 26, 6, 18, 0),
+    children: (
+      <div style={{ backgroundColor: 'indigo', height: '100%' }}>7-25 14:45 ~ 7-26 6:18</div>
+    ),
+  },
+  {
+    start: new Date(2019, 6, 25, 8, 0, 0),
+    end: new Date(2019, 6, 27, 6, 0, 0),
+    children: (
+      <div style={{ backgroundColor: 'indigo', height: '100%' }}>7-25 8:00 ~ 7-27 6:00</div>
+    ),
+  },
+  {
+    start: new Date(2019, 6, 22, 9, 0, 0),
+    end: new Date(2019, 6, 23, 23, 0, 0),
+    children: (
+      <div style={{ backgroundColor: 'LightSkyBlue', height: '100%' }}>7-22 9:00 ~ 7-23 23:00</div>
+    ),
+  },
+  {
+    start: new Date(2019, 6, 21, 6, 0, 0),
+    end: new Date(2019, 6, 25, 6, 0, 0),
+    children: (
+      <div style={{ backgroundColor: 'YellowGreen', height: '100%' }}>7-21 6:00 ~ 7-25 6:00</div>
+    ),
+  },
+  {
+    start: new Date(2019, 6, 19, 20, 0, 0),
+    end: new Date(2019, 6, 23, 14, 0, 0),
+    children: (
+      <div style={{ backgroundColor: 'pink', height: '100%' }}>7-19 20:00 ~ 7-23 14:00</div>
+    ),
+  },
+  {
+    start: new Date(2019, 6, 26, 10, 0, 0),
+    end: new Date(2019, 6, 27, 16, 0, 0),
+    children: <div style={{ backgroundColor: 'red', height: '100%' }}>7-26 10:00 ~ 7-27 16:00</div>,
+  },
+  {
+    start: new Date(2019, 6, 18, 10, 0, 0),
+    end: new Date(2019, 6, 30, 8, 0, 0),
+    children: (
+      <div style={{ backgroundColor: 'green', height: '100%' }}>7-18 10:00 ~ 7-30 8:00</div>
+    ),
+  },
+];
 
-stories.add('weekCalendar', () => {
-    return (
-        <div>
-            <Calendar
-                displayValue={date}
-                events={weeklyEvents}
-            ></Calendar>
-        </div>
-    );
-});
+export const DayCalendar = () => {
+  return (
+    <div>
+      <Calendar
+        mode="day"
+        events={events}
+        // displayValue={new Date(2019, 6, 16, 8, 0, 0)}
+      ></Calendar>
+    </div>
+  );
+};
 
-stories.add('this week calendar', () => {
-    return (
-        <div>
-            <Calendar
-                events={weeklyEvents2}
-                displayValue={new Date(2019, 6, 22, 8, 0, 0)}
-            ></Calendar>
-        </div>
-    );
-});
+DayCalendar.parameters = {
+  chromatic: { disableSnapshot: true },
+}
 
-stories.add('month calendar', () => {
-    return (
-        <Calendar
-            events={[...weeklyEvents2, ...weeklyEvents]}
-            mode='month'
-        ></Calendar>
-    );
-});
+export const WeekCalendar = () => {
+  return (
+    <div>
+      <Calendar displayValue={date} events={weeklyEvents}></Calendar>
+    </div>
+  );
+};
 
-const AddDemo = () => {
-    const [event, setEvent] = useState([]);
-    const [mode, setMode] = useState('day');
+export const ThisWeekCalendar = () => {
+  return (
+    <div>
+      <Calendar events={weeklyEvents2} displayValue={new Date(2019, 6, 22, 8, 0, 0)}></Calendar>
+    </div>
+  );
+};
 
-    const addEvent = () => {
-        let newEvent = {
-            allDay: true,
-            start: new Date(),
-            key: `${id}`,
-            children: (<div style={allDayStyle}>today-{id}</div>)
-        };
-        id++;
-        setEvent([...event, newEvent]);
-    }
+export const MonthCalendar = () => {
+  return <Calendar events={[...weeklyEvents2, ...weeklyEvents]} mode="month"></Calendar>;
+};
 
-    const removeEvent = () => {
-        let newEvents = [...event];
-        newEvents.pop();
-        setEvent([...newEvents]);
-    }
-    return (
-        <>
-            <Button onClick={addEvent}>add</Button>
-            <Button onClick={removeEvent}>remove</Button>
-            <RadioGroup onChange={(e) => setMode(e.target.value)} value={mode}>
-                <Radio value={'day'}>日视图</Radio>
-                <Radio value={'week'}>周视图</Radio>
-                <Radio value={'month'}>月视图</Radio>
-            </RadioGroup>
-            <Calendar
-                events={event}
-                mode={mode}
-            />
-        </>
-    );
+MonthCalendar.parameters = {
+  chromatic: { disableSnapshot: true },
 }
 
-stories.add('add event to calendar', () => <AddDemo />);
+const AddEventToCalendar = () => {
+  const [event, setEvent] = useState([]);
+  const [mode, setMode] = useState('day');
+
+  const addEvent = () => {
+    let newEvent = {
+      allDay: true,
+      start: new Date(),
+      key: `${id}`,
+      children: <div style={allDayStyle}>today-{id}</div>,
+    };
+    id++;
+    setEvent([...event, newEvent]);
+  };
 
+  const removeEvent = () => {
+    let newEvents = [...event];
+    newEvents.pop();
+    setEvent([...newEvents]);
+  };
+  return (
+    <>
+      <Button onClick={addEvent}>add</Button>
+      <Button onClick={removeEvent}>remove</Button>
+      <RadioGroup onChange={e => setMode(e.target.value)} value={mode}>
+        <Radio value={'day'}>日视图</Radio>
+        <Radio value={'week'}>周视图</Radio>
+        <Radio value={'month'}>月视图</Radio>
+      </RadioGroup>
+      <Calendar events={event} mode={mode} />
+    </>
+  );
+};
 
-const UpdateDemo = () => {
-    const [event, setEvent] = useState([]);
-    const [mode, setMode] = useState('day');
-    const [updateId, setId] = useState(id);
+export const UpdateEvent = () => {
+  const [event, setEvent] = useState([]);
+  const [mode, setMode] = useState('day');
+  const [updateId, setId] = useState(id);
 
-    const addEvent = () => {
-        let key = `${id}`;
-        let newEvent = {
-            allDay: true,
-            start: new Date(),
-            key,
-            children: (<div style={allDayStyle} onClick={() => {
-                console.log(key);
-                setId(key);
-            }}>today-{key}</div>),
+  const addEvent = () => {
+    let key = `${id}`;
+    let newEvent = {
+      allDay: true,
+      start: new Date(),
+      key,
+      children: (
+        <div
+          style={allDayStyle}
+          onClick={() => {
+            console.log(key);
+            setId(key);
+          }}
+        >
+          today-{key}
+        </div>
+      ),
+    };
+    id++;
+    setEvent([...event, newEvent]);
+  };
 
-        };
-        id++;
-        setEvent([...event, newEvent]);
-    }
+  const updateEvent = () => {
+    let ind = event.findIndex(item => {
+      return item.key === updateId;
+    });
+    let newArr = [...event];
+    newArr[ind].key = `${Math.random()}`;
+    newArr[ind].children = <div style={allDayStyle}>today-{Math.random(0, 1)}</div>;
+    setEvent(newArr);
+  };
 
-    const updateEvent = () => {
-        let ind = event.findIndex(item => {
-            return item.key === updateId;
-        });
-        let newArr = [...event];
-        newArr[ind].key = `${Math.random()}`
-        newArr[ind].children = (<div style={allDayStyle}>today-{Math.random(0, 1)}</div>)
-        setEvent(newArr);
-    }
+  return (
+    <>
+      <Button onClick={addEvent}>add</Button>
+      <Button onClick={updateEvent}>update</Button>
+      <RadioGroup onChange={e => setMode(e.target.value)} value={mode}>
+        <Radio value={'day'}>日视图</Radio>
+        <Radio value={'week'}>周视图</Radio>
+        <Radio value={'month'}>月视图</Radio>
+      </RadioGroup>
+      <Calendar events={event} mode={mode} />
+    </>
+  );
+};
 
-    return (
-        <>
-            <Button onClick={addEvent}>add</Button>
-            <Button onClick={updateEvent}>update</Button>
-            <RadioGroup onChange={(e) => setMode(e.target.value)} value={mode}>
-                <Radio value={'day'}>日视图</Radio>
-                <Radio value={'week'}>周视图</Radio>
-                <Radio value={'month'}>月视图</Radio>
-            </RadioGroup>
-            <Calendar
-                events={event}
-                mode={mode}
-            />
-        </>
-    );
+UpdateEvent.parameters = {
+  chromatic: { disableSnapshot: true },
 }
 
-stories.add('update event', () => <UpdateDemo />);
+export const DateGridRenderWeek = () => {
+  return (
+    <div>
+      <Calendar
+        displayValue={date}
+        events={weeklyEvents}
+        dateGridRender={(dateString, date) => {
+          if (dateString === new Date(2019, 6, 16).toString()) {
+            return (
+              <div style={{ backgroundColor: 'red', height: '100%', width: '100%' }}>123test</div>
+            );
+          }
+          return null;
+        }}
+      ></Calendar>
+    </div>
+  );
+};
 
-stories.add('dateGridRender - week', () => {
-    return (
-        <div>
-            <Calendar
-                displayValue={date}
-                events={weeklyEvents}
-                dateGridRender={(dateString, date) => {
-                    if (dateString === new Date(2019, 6, 16).toString()) {
-                        return <div style={{ backgroundColor: 'red', height: '100%', width: '100%' }}>123test</div>
-                    }
-                    return null;
-                }}
-            ></Calendar>
-        </div>
-    );
-});
+export const DateGridRenderMonth = () => {
+  return (
+    <div>
+      <Calendar
+        mode="month"
+        displayValue={date}
+        events={weeklyEvents}
+        dateGridRender={(dateString, date) => {
+          console.log(dateString);
+          if (dateString === new Date(2019, 6, 16).toString()) {
+            return (
+              <div style={{ backgroundColor: 'red', height: '100%', width: '100%' }}>123test</div>
+            );
+          }
+          return null;
+        }}
+      ></Calendar>
+    </div>
+  );
+};
 
-stories.add('dateGridRender - month', () => {
-    return (
-        <div>
-            <Calendar
-                mode='month'
-                displayValue={date}
-                events={weeklyEvents}
-                dateGridRender={(dateString, date) => {
-                    console.log(dateString)
-                    if (dateString === new Date(2019, 6, 16).toString()) {
-                        return <div style={{ backgroundColor: 'red', height: '100%', width: '100%' }}>123test</div>
-                    }
-                    return null;
-                }}
-            ></Calendar>
-        </div>
-    );
-});
+export const RangeCalenderMonth = () => {
+  return (
+    <div>
+      <Calendar
+        mode={'range'}
+        range={[new Date(2019, 6, 22), new Date(2019, 6, 25)]}
+        events={weeklyEvents2}
+        displayValue={new Date(2019, 6, 22)}
+      />
+    </div>
+  );
+};
 
-stories.add('rangecalender - month', () => {
-    return (
-        <div>
-            <Calendar
-                mode={'range'}
-                range={[new Date(2019, 6, 22), new Date(2019, 6, 25)]}
-                events={weeklyEvents2}
-                displayValue={new Date(2019, 6, 22)}
-            />
-        </div>
-    );
-});
+export const WithLocaleProvider = () => {
+  const [locale, setLocale] = useState(zh_CN);
+  const onLanguageChange = code => {
+    setLocale(language[code]);
+  };
 
-stories.add('locale provider', () => {
-    const [locale, setLocale] = useState(zh_CN);
-    const onLanguageChange = (code) => {
-        setLocale(language[code]);
-    };
+  return (
+    <LocaleProvider>
+      <div style={{ borderBottom: '1px solid var(--semi-color-border)', paddingBottom: 20 }}>
+        <Select
+          onChange={onLanguageChange}
+          insetLabel="切换语言"
+          style={{ width: 250 }}
+          defaultValue="zh_CN"
+        >
+          <Option value="zh_CN">中文</Option>
+          <Option value="en_GB">英语(英)</Option>
+          <Option value="ja_JP">日语</Option>
+          <Option value="ko_KR">韩语</Option>
+          <Option value="ar">阿拉伯语</Option>
+          <Option value="vi_VN">越南语</Option>
+          <Option value="ru_RU">俄罗斯语</Option>
+          <Option value="id_ID">印尼语</Option>
+          <Option value="ms_MY">马来语</Option>
+          <Option value="th_TH">泰语</Option>
+          <Option value="tr_TR">土耳其语</Option>
+          <Option value="pt_BR">葡萄牙语(巴西)</Option>
+        </Select>
+      </div>
+      <LocaleProvider locale={locale}>
+        <Calendar mode="day" />
+        <br />
+        <Calendar mode="week" />
+        <br />
+        <Calendar mode="month" />
+        <br />
+      </LocaleProvider>
+    </LocaleProvider>
+  );
+};
 
-    return (
-        <LocaleProvider>
-            <div style={{ borderBottom: '1px solid var(--semi-color-border)', paddingBottom: 20 }}>
-                <Select onChange={onLanguageChange} insetLabel='切换语言' style={{width: 250}} defaultValue='zh_CN'>
-                    <Option value='zh_CN'>中文</Option>
-                    <Option value='en_GB'>英语(英)</Option>
-                    <Option value='ja_JP'>日语</Option>
-                    <Option value='ko_KR'>韩语</Option>
-                    <Option value='ar'>阿拉伯语</Option>
-                    <Option value='vi_VN'>越南语</Option>
-                    <Option value='ru_RU'>俄罗斯语</Option>
-                    <Option value='id_ID'>印尼语</Option>
-                    <Option value='ms_MY'>马来语</Option>
-                    <Option value='th_TH'>泰语</Option>
-                    <Option value='tr_TR'>土耳其语</Option>
-                    <Option value='pt_BR'>葡萄牙语(巴西)</Option>
-                </Select>
-            </div>
-            <LocaleProvider locale={locale}>
-                <Calendar mode='day' /><br />
-                <Calendar mode='week' /><br />
-                <Calendar mode='month' /><br />
-            </LocaleProvider>
-        </LocaleProvider>
-    );
-});
+WithLocaleProvider.parameters = {
+  chromatic: { disableSnapshot: true }
+}

+ 514 - 498
packages/semi-ui/card/_story/card.stories.js

@@ -1,539 +1,555 @@
 import React, { useState } from 'react';
-import { storiesOf } from '@storybook/react';
 import {
-    Space,
-    Button,
-    Avatar,
-    Typography,
-    Row,
-    Tabs,
-    TabPane,
-    Col,
-    Skeleton,
-    Switch,
-    Rating,
+  Space,
+  Button,
+  Avatar,
+  Typography,
+  Row,
+  Tabs,
+  TabPane,
+  Col,
+  Skeleton,
+  Switch,
+  Rating,
 } from '@douyinfe/semi-ui/';
 import Card from '../index';
 import CardGroup from '../cardGroup';
-import { IconChevronRight, IconLikeThumb, IconLikeHeart, IconEdit, IconWrench } from '@douyinfe/semi-icons';
+import {
+  IconChevronRight,
+  IconLikeThumb,
+  IconLikeHeart,
+  IconEdit,
+  IconWrench,
+} from '@douyinfe/semi-icons';
 
-const stories = storiesOf('Card', module);
 const { Text } = Typography;
 const { Meta } = Card;
-stories.add('default', () => (
-    <Space wrap>
-        <Card
-            title="基础卡片"
-            style={{
-                width: 360,
-            }}
-            headerExtraContent={<Text link={{}}>更多</Text>}
-        >
-            Semi Design 是由互娱社区前端团队与 UED
-            团队共同设计开发并维护的设计系统。设计系统包含设计语言以及一整套可复用的前端组件,帮助设计师与开发者更容易地打造高质量的、用户体验一致的、符合设计规范的
-            Web 应用。
-        </Card>
-        <Card
-            title="titleisstringtitleisstringtitleisstringtitleisstringtitleisstring"
-            style={{
-                width: 360,
-            }}
-            headerExtraContent={<Text link={{}}>更多</Text>}
-        >
-            Semi Design 是由互娱社区前端团队与 UED
-            团队共同设计开发并维护的设计系统。设计系统包含设计语言以及一整套可复用的前端组件,帮助设计师与开发者更容易地打造高质量的、用户体验一致的、符合设计规范的
-            Web 应用。
-        </Card>
-        <Card
-            title="标题为字符串标题特别长标题特别长标题特别长标题特别长标题特别长"
-            style={{
-                width: 360,
-            }}
-            headerExtraContent={<Text link={{}}>更多</Text>}
-        >
-            Semi Design 是由互娱社区前端团队与 UED
-            团队共同设计开发并维护的设计系统。设计系统包含设计语言以及一整套可复用的前端组件,帮助设计师与开发者更容易地打造高质量的、用户体验一致的、符合设计规范的
-            Web 应用。
-        </Card>
-        <Card
-            title={<div>标题为node标题特别长标题特别长标题特别长标题特别长标题特别长</div>}
-            style={{
-                width: 360,
-            }}
-            headerExtraContent={<Text link={{}}>更多</Text>}
-        >
-            Semi Design 是由互娱社区前端团队与 UED
-            团队共同设计开发并维护的设计系统。设计系统包含设计语言以及一整套可复用的前端组件,帮助设计师与开发者更容易地打造高质量的、用户体验一致的、符合设计规范的
-            Web 应用。
-        </Card>
-        <Card
-            header={<div>头部内容为node头部内容特别长头部内容特别长头部内容特别长头部内容特别长头部内容特别长</div>}
-            style={{
-                width: 360,
-            }}
-            headerExtraContent={<Text link={{}}>更多</Text>}
-        >
-            Semi Design 是由互娱社区前端团队与 UED
-            团队共同设计开发并维护的设计系统。设计系统包含设计语言以及一整套可复用的前端组件,帮助设计师与开发者更容易地打造高质量的、用户体验一致的、符合设计规范的
-            Web 应用。
-        </Card>
-        <Card
-            header={<div>headerheaderheaderheaderheaderheaderheaderheaderheaderheader</div>}
-            style={{
-                width: 360,
-            }}
-            headerExtraContent={<Text link={{}}>更多</Text>}
-        >
-            Semi Design 是由互娱社区前端团队与 UED
-            团队共同设计开发并维护的设计系统。设计系统包含设计语言以及一整套可复用的前端组件,帮助设计师与开发者更容易地打造高质量的、用户体验一致的、符合设计规范的
-            Web 应用。
-        </Card>
-    </Space>
-));
 
-function SimpleDemo() {
-    return (
-        <Space align="start" vertical spacing="medium">
-            <Card
-                style={{
-                    width: 360,
-                }}
-            >
-                Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统。
-            </Card>
-            <Card
-                style={{
-                    width: 360,
-                }}
-                bodyStyle={{
-                    display: 'flex',
-                    alignItems: 'center',
-                    justifyContent: 'space-between',
-                }}
-            >
-                <Meta
-                    title="Semi Doc"
-                    avatar={
-                        <Avatar
-                            size="default"
-                            src="https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/card-meta-avatar-docs-demo.jpg"
-                        />
-                    }
-                />
-                <Text link={{}}>
-                    <IconChevronRight />
-                </Text>
-            </Card>
-        </Space>
-    );
+export default {
+  title: 'Card',
 }
 
-stories.add('simple ', () => <SimpleDemo />);
-stories.add('cover ', () => (
+export const Default = () => (
+  <Space wrap>
     <Card
-        style={{
-            width: 360,
-        }}
-        cover={
-            <img
-                alt="example"
-                src="https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/card-cover-docs-demo.jpeg"
-            />
-        }
+      title="基础卡片"
+      style={{
+        width: 360,
+      }}
+      headerExtraContent={<Text link={{}}>更多</Text>}
     >
-        <Meta title="卡片封面" />
+      Semi Design 是由互娱社区前端团队与 UED
+      团队共同设计开发并维护的设计系统。设计系统包含设计语言以及一整套可复用的前端组件,帮助设计师与开发者更容易地打造高质量的、用户体验一致的、符合设计规范的
+      Web 应用。
     </Card>
-));
-stories.add('bordered', () => (
-    <div
-        style={{
-            display: 'inline-block',
-            padding: 20,
-            backgroundColor: 'var(--semi-color-fill-0)',
-        }}
+    <Card
+      title="titleisstringtitleisstringtitleisstringtitleisstringtitleisstring"
+      style={{
+        width: 360,
+      }}
+      headerExtraContent={<Text link={{}}>更多</Text>}
     >
-        <Card
-            style={{
-                width: 360,
-            }}
-            bordered={false}
-            title="Semi Design"
-        >
-            基于 Semi Design 的中后台设计案例聚合分享平台,海量案例和模板代码助力体验 & 效率提升。
-        </Card>
-    </div>
-));
-stories.add('headerLine / footerLine', () => (
+      Semi Design 是由互娱社区前端团队与 UED
+      团队共同设计开发并维护的设计系统。设计系统包含设计语言以及一整套可复用的前端组件,帮助设计师与开发者更容易地打造高质量的、用户体验一致的、符合设计规范的
+      Web 应用。
+    </Card>
     <Card
-        style={{
-            width: 360,
-        }}
-        title="Semi Design"
-        headerLine={true}
-        footerLine={false}
-        footer="footer"
+      title="标题为字符串标题特别长标题特别长标题特别长标题特别长标题特别长"
+      style={{
+        width: 360,
+      }}
+      headerExtraContent={<Text link={{}}>更多</Text>}
     >
-        基于 Semi Design 的中后台设计案例聚合分享平台,海量案例和模板代码助力体验 & 效率提升。
+      Semi Design 是由互娱社区前端团队与 UED
+      团队共同设计开发并维护的设计系统。设计系统包含设计语言以及一整套可复用的前端组件,帮助设计师与开发者更容易地打造高质量的、用户体验一致的、符合设计规范的
+      Web 应用。
     </Card>
-));
-stories.add('shadows', () => (
-    <Space>
-        <Card
-            style={{
-                width: 360,
-            }}
-            title="没有设置shadows"
-        >
-            基于 Semi Design 的中后台设计案例聚合分享平台,海量案例和模板代码助力体验 & 效率提升。
-        </Card>
-        <Card
-            style={{
-                width: 360,
-            }}
-            title="shadows为hover"
-            shadows="hover"
-        >
-            基于 Semi Design 的中后台设计案例聚合分享平台,海量案例和模板代码助力体验 & 效率提升。
-        </Card>
-        <Card
-            style={{
-                width: 360,
-            }}
-            title="shadows为always"
-            shadows="always"
-        >
-            基于 Semi Design 的中后台设计案例聚合分享平台,海量案例和模板代码助力体验 & 效率提升。
-        </Card>
-    </Space>
-));
-stories.add('Card.Meta', () => (
     <Card
+      title={<div>标题为node标题特别长标题特别长标题特别长标题特别长标题特别长</div>}
+      style={{
+        width: 360,
+      }}
+      headerExtraContent={<Text link={{}}>更多</Text>}
+    >
+      Semi Design 是由互娱社区前端团队与 UED
+      团队共同设计开发并维护的设计系统。设计系统包含设计语言以及一整套可复用的前端组件,帮助设计师与开发者更容易地打造高质量的、用户体验一致的、符合设计规范的
+      Web 应用。
+    </Card>
+    <Card
+      header={
+        <div>
+          头部内容为node头部内容特别长头部内容特别长头部内容特别长头部内容特别长头部内容特别长
+        </div>
+      }
+      style={{
+        width: 360,
+      }}
+      headerExtraContent={<Text link={{}}>更多</Text>}
+    >
+      Semi Design 是由互娱社区前端团队与 UED
+      团队共同设计开发并维护的设计系统。设计系统包含设计语言以及一整套可复用的前端组件,帮助设计师与开发者更容易地打造高质量的、用户体验一致的、符合设计规范的
+      Web 应用。
+    </Card>
+    <Card
+      header={<div>headerheaderheaderheaderheaderheaderheaderheaderheaderheader</div>}
+      style={{
+        width: 360,
+      }}
+      headerExtraContent={<Text link={{}}>更多</Text>}
+    >
+      Semi Design 是由互娱社区前端团队与 UED
+      团队共同设计开发并维护的设计系统。设计系统包含设计语言以及一整套可复用的前端组件,帮助设计师与开发者更容易地打造高质量的、用户体验一致的、符合设计规范的
+      Web 应用。
+    </Card>
+  </Space>
+);
+
+export function Simple() {
+  return (
+    <Space align="start" vertical spacing="medium">
+      <Card
         style={{
-            width: 360,
+          width: 360,
         }}
-        title={
-            <Meta
-                title="Semi Doc"
-                description="全面、易用、优质"
-                avatar={
-                    <Avatar
-                        size="default"
-                        src="https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/card-meta-avatar-docs-demo.jpg"
-                    />
-                }
-            />
-        }
-        headerExtraContent={<Text link={{}}>More</Text>}
-        cover={
-            <img
-                alt="example"
-                src="https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/card-cover-docs-demo.jpeg"
-            />
-        }
-        footerLine={true}
-        footerStyle={{
-            display: 'flex',
-            justifyContent: 'flex-end',
+      >
+        Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统。
+      </Card>
+      <Card
+        style={{
+          width: 360,
         }}
-        footer={
-            <Space>
-                <Button theme="borderless" type="primary">
-                    精选案例
-                </Button>
-                <Button theme="solid" type="primary">
-                    开始使用
-                </Button>
-            </Space>
-        }
+        bodyStyle={{
+          display: 'flex',
+          alignItems: 'center',
+          justifyContent: 'space-between',
+        }}
+      >
+        <Meta
+          title="Semi Doc"
+          avatar={
+            <Avatar
+              size="default"
+              src="https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/card-meta-avatar-docs-demo.jpg"
+            />
+          }
+        />
+        <Text link={{}}>
+          <IconChevronRight />
+        </Text>
+      </Card>
+    </Space>
+  );
+}
+
+export const Cover = () => (
+  <Card
+    style={{
+      width: 360,
+    }}
+    cover={
+      <img
+        alt="example"
+        src="https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/card-cover-docs-demo.jpeg"
+      />
+    }
+  >
+    <Meta title="卡片封面" />
+  </Card>
+);
+
+export const Bordered = () => (
+  <div
+    style={{
+      display: 'inline-block',
+      padding: 20,
+      backgroundColor: 'var(--semi-color-fill-0)',
+    }}
+  >
+    <Card
+      style={{
+        width: 360,
+      }}
+      bordered={false}
+      title="Semi Design"
     >
-        Semi Design 是由互娱社区前端团队与 UED
-        团队共同设计开发并维护的设计系统。设计系统包含设计语言以及一整套可复用的前端组件,帮助设计师与开发者更容易地打造高质量的、用户体验一致的、符合设计规范的
-        Web 应用。
+      基于 Semi Design 的中后台设计案例聚合分享平台,海量案例和模板代码助力体验 & 效率提升。
     </Card>
-));
-stories.add('inner', () => (
+  </div>
+);
+
+export const HeaderLineFooterLine = () => (
+  <Card
+    style={{
+      width: 360,
+    }}
+    title="Semi Design"
+    headerLine={true}
+    footerLine={false}
+    footer="footer"
+  >
+    基于 Semi Design 的中后台设计案例聚合分享平台,海量案例和模板代码助力体验 & 效率提升。
+  </Card>
+);
+
+export const Shadows = () => (
+  <Space>
     <Card
-        title="Card title"
-        style={{
-            width: 360,
-        }}
+      style={{
+        width: 360,
+      }}
+      title="没有设置shadows"
     >
-        <Card
-            title="Inner Card title"
-            style={{
-                marginBottom: 20,
-            }}
-            headerExtraContent={<Text link={{}}>More</Text>}
-        >
-            Inner Card content
+      基于 Semi Design 的中后台设计案例聚合分享平台,海量案例和模板代码助力体验 & 效率提升。
+    </Card>
+    <Card
+      style={{
+        width: 360,
+      }}
+      title="shadows为hover"
+      shadows="hover"
+    >
+      基于 Semi Design 的中后台设计案例聚合分享平台,海量案例和模板代码助力体验 & 效率提升。
+    </Card>
+    <Card
+      style={{
+        width: 360,
+      }}
+      title="shadows为always"
+      shadows="always"
+    >
+      基于 Semi Design 的中后台设计案例聚合分享平台,海量案例和模板代码助力体验 & 效率提升。
+    </Card>
+  </Space>
+);
+
+export const MetaDemo = () => (
+  <Card
+    style={{
+      width: 360,
+    }}
+    title={
+      <Meta
+        title="Semi Doc"
+        description="全面、易用、优质"
+        avatar={
+          <Avatar
+            size="default"
+            src="https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/card-meta-avatar-docs-demo.jpg"
+          />
+        }
+      />
+    }
+    headerExtraContent={<Text link={{}}>More</Text>}
+    cover={
+      <img
+        alt="example"
+        src="https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/card-cover-docs-demo.jpeg"
+      />
+    }
+    footerLine={true}
+    footerStyle={{
+      display: 'flex',
+      justifyContent: 'flex-end',
+    }}
+    footer={
+      <Space>
+        <Button theme="borderless" type="primary">
+          精选案例
+        </Button>
+        <Button theme="solid" type="primary">
+          开始使用
+        </Button>
+      </Space>
+    }
+  >
+    Semi Design 是由互娱社区前端团队与 UED
+    团队共同设计开发并维护的设计系统。设计系统包含设计语言以及一整套可复用的前端组件,帮助设计师与开发者更容易地打造高质量的、用户体验一致的、符合设计规范的
+    Web 应用。
+  </Card>
+);
+
+export const Inner = () => (
+  <Card
+    title="Card title"
+    style={{
+      width: 360,
+    }}
+  >
+    <Card
+      title="Inner Card title"
+      style={{
+        marginBottom: 20,
+      }}
+      headerExtraContent={<Text link={{}}>More</Text>}
+    >
+      Inner Card content
+    </Card>
+    <Card title="Inner Card title" headerExtraContent={<Text link={{}}>More</Text>}>
+      Inner Card content
+    </Card>
+  </Card>
+);
+
+export const Grid = () => (
+  <div
+    style={{
+      backgroundColor: 'var(--semi-color-fill-0)',
+      padding: 20,
+    }}
+  >
+    <Row gutter={[16, 16]}>
+      <Col span={8}>
+        <Card title="Card Title" bordered={false}>
+          Card Content
         </Card>
-        <Card title="Inner Card title" headerExtraContent={<Text link={{}}>More</Text>}>
-            Inner Card content
+      </Col>
+      <Col span={8}>
+        <Card title="Card Title" bordered={false}>
+          Card Content
         </Card>
-    </Card>
-));
-stories.add('grid', () => (
-    <div
+      </Col>
+      <Col span={8}>
+        <Card title="Card Title" bordered={false}>
+          Card Content
+        </Card>
+      </Col>
+    </Row>
+    <Row gutter={[16, 16]}>
+      <Col span={16}>
+        <Card title="Card Title" bordered={false}>
+          Card Content
+        </Card>
+      </Col>
+      <Col span={8}>
+        <Card title="Card Title" bordered={false}>
+          Card Content
+        </Card>
+      </Col>
+    </Row>
+  </div>
+);
+
+export function Loading() {
+  const [loading, setLoading] = useState(true);
+  const { Meta } = Card;
+  const { Title, Paragraph, Image } = Skeleton;
+  return (
+    <Space vertical align="start" spacing="medium">
+      <Switch onChange={v => setLoading(!v)} />
+      <Card
         style={{
-            backgroundColor: 'var(--semi-color-fill-0)',
-            padding: 20,
+          width: 360,
         }}
-    >
-        <Row gutter={[16, 16]}>
-            <Col span={8}>
-                <Card title="Card Title" bordered={false}>
-                    Card Content
-                </Card>
-            </Col>
-            <Col span={8}>
-                <Card title="Card Title" bordered={false}>
-                    Card Content
-                </Card>
-            </Col>
-            <Col span={8}>
-                <Card title="Card Title" bordered={false}>
-                    Card Content
-                </Card>
-            </Col>
-        </Row>
-        <Row gutter={[16, 16]}>
-            <Col span={16}>
-                <Card title="Card Title" bordered={false}>
-                    Card Content
-                </Card>
-            </Col>
-            <Col span={8}>
-                <Card title="Card Title" bordered={false}>
-                    Card Content
-                </Card>
-            </Col>
-        </Row>
-    </div>
-));
-
-function LoadingDemo() {
-    const [loading, setLoading] = useState(true);
-    const { Meta } = Card;
-    const { Title, Paragraph, Image } = Skeleton;
-    return (
-        <Space vertical align="start" spacing="medium">
-            <Switch onChange={v => setLoading(!v)} />
-            <Card
+        loading={loading}
+      >
+        <Meta title="Semi Doc" description="全面、易用、优质" />
+      </Card>
+      <Card
+        style={{
+          width: 360,
+        }}
+        title={
+          <Meta
+            title={
+              <Skeleton
                 style={{
-                    width: 360,
+                  width: 80,
                 }}
+                placeholder={<Title />}
                 loading={loading}
-            >
-                <Meta title="Semi Doc" description="全面、易用、优质" />
-            </Card>
-            <Card
+              >
+                <Typography.Title heading={5}>Semi Doc</Typography.Title>
+              </Skeleton>
+            }
+            description={
+              <Skeleton
                 style={{
-                    width: 360,
+                  width: 150,
+                  marginTop: 12,
                 }}
-                title={
-                    <Meta
-                        title={
-                            <Skeleton
-                                style={{
-                                    width: 80,
-                                }}
-                                placeholder={<Title />}
-                                loading={loading}
-                            >
-                                <Typography.Title heading={5}>Semi Doc</Typography.Title>
-                            </Skeleton>
-                        }
-                        description={
-                            <Skeleton
-                                style={{
-                                    width: 150,
-                                    marginTop: 12,
-                                }}
-                                placeholder={<Paragraph rows={1} />}
-                                loading={loading}
-                            >
-                                <Typography.Text>全面、易用、优质</Typography.Text>
-                            </Skeleton>
-                        }
-                        avatar={
-                            <Skeleton placeholder={<Skeleton.Avatar />} loading={loading}>
-                                <Avatar
-                                    size="default"
-                                    src="https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/card-meta-avatar-docs-demo.jpg"
-                                />
-                            </Skeleton>
-                        }
-                    />
-                }
-                headerExtraContent={
-                    <Skeleton
-                        style={{
-                            width: 50,
-                        }}
-                        placeholder={<Paragraph rows={1} />}
-                        loading={loading}
-                    >
-                        <Typography.Text link={{}}>More</Typography.Text>
-                    </Skeleton>
-                }
-                cover={
-                    <Skeleton
-                        style={{
-                            width: '100%',
-                            height: 110,
-                        }}
-                        placeholder={<Image />}
-                        loading={loading}
-                    >
-                        <img
-                            alt="example"
-                            src="https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/card-cover-docs-demo.jpeg"
-                        />
-                    </Skeleton>
-                }
-            ></Card>
-        </Space>
-    );
-}
-
-stories.add('loading', () => <LoadingDemo />);
-stories.add('tabs', () => (
-    <Card title="Card title">
-        <Tabs
-            type="line"
-            style={{
-                marginTop: -20,
-                marginBottom: -20,
-            }}
-        >
-            <TabPane tab="Tab 1" itemKey="1">
-                <p>content1</p>
-                <p>content1</p>
-                <p>content1</p>
-            </TabPane>
-            <TabPane tab="Tab 2" itemKey="2">
-                <p>content2</p>
-                <p>content2</p>
-                <p>content2</p>
-            </TabPane>
-        </Tabs>
-    </Card>
-));
-stories.add('actions', () => (
-    <Space align="start">
-        <Card
-            style={{
-                width: 360,
-            }}
-            title={
-                <Meta
-                    title="Semi Doc"
-                    description="全面、易用、优质"
-                    avatar={
-                        <Avatar
-                            size="default"
-                            src="https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/card-meta-avatar-docs-demo.jpg"
-                        />
-                    }
+                placeholder={<Paragraph rows={1} />}
+                loading={loading}
+              >
+                <Typography.Text>全面、易用、优质</Typography.Text>
+              </Skeleton>
+            }
+            avatar={
+              <Skeleton placeholder={<Skeleton.Avatar />} loading={loading}>
+                <Avatar
+                  size="default"
+                  src="https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/card-meta-avatar-docs-demo.jpg"
                 />
+              </Skeleton>
             }
-            actions={[<Rating defaultValue={4} />]}
-            headerLine={false}
-            footerLine={false}
-            footerStyle={{
-                display: 'flex',
-                justifyContent: 'flex-end',
+          />
+        }
+        headerExtraContent={
+          <Skeleton
+            style={{
+              width: 50,
             }}
-            footer={
-                <Space>
-                    <Button theme="solid" type="primary">
-                        打分
-                    </Button>
-                </Space>
-            }
-        >
-            Semi Design 是由互娱社区前端团队与 UED
-            团队共同设计开发并维护的设计系统。设计系统包含设计语言以及一整套可复用的前端组件,帮助设计师与开发者更容易地打造高质量的、用户体验一致的、符合设计规范的
-            Web 应用。
-        </Card>
-        <Card
+            placeholder={<Paragraph rows={1} />}
+            loading={loading}
+          >
+            <Typography.Text link={{}}>More</Typography.Text>
+          </Skeleton>
+        }
+        cover={
+          <Skeleton
             style={{
-                width: 360,
+              width: '100%',
+              height: 110,
             }}
-            title={
-                <Meta
-                    title="Semi Doc"
-                    description="全面、易用、优质"
-                    avatar={
-                        <Avatar
-                            size="default"
-                            src="https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/card-meta-avatar-docs-demo.jpg"
-                        />
-                    }
-                />
-            }
-            actions={[
-                <IconLikeThumb />,
-                <IconLikeHeart />,
-                <IconEdit />,
-                <IconWrench />,
-            ]}
-            headerLine={false}
-        >
-            Semi Design 是由互娱社区前端团队与 UED
-            团队共同设计开发并维护的设计系统。设计系统包含设计语言以及一整套可复用的前端组件,帮助设计师与开发者更容易地打造高质量的、用户体验一致的、符合设计规范的
-            Web 应用。
-        </Card>
+            placeholder={<Image />}
+            loading={loading}
+          >
+            <img
+              alt="example"
+              src="https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/card-cover-docs-demo.jpeg"
+            />
+          </Skeleton>
+        }
+      ></Card>
     </Space>
-));
-stories.add('CardGroup', () => (
-    <CardGroup spacing={12}>
-        {new Array(3).fill(null).map((v, idx) => (
-            <Card
-                key={idx}
-                style={{
-                    width: 300,
-                }}
-                title={
-                    <Meta
-                        title="Semi Doc"
-                        description="全面、易用、优质"
-                        avatar={
-                            <Avatar
-                                size="default"
-                                src="https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/card-meta-avatar-docs-demo.jpg"
-                            />
-                        }
-                    />
-                }
-                headerExtraContent={<Text link>More</Text>}
-                cover={
-                    <img
-                        alt="example"
-                        src="https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/card-cover-docs-demo.jpeg"
-                    />
-                }
-            >
-                Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统。
-            </Card>
-        ))}
-    </CardGroup>
-));
-stories.add('CardGroup-grid', () => (
-    <CardGroup type="grid">
-        {new Array(7).fill(null).map((v, idx) => (
-            <Card
-                key={idx}
-                shadows="hover"
-                title="Card title"
-                headerLine={false}
-                style={{
-                    width: 260,
-                }}
-                headerExtraContent={<Text link>More</Text>}
-            >
-                <Text>Card content</Text>
-            </Card>
-        ))}
-    </CardGroup>
-));
+  );
+}
+
+
+export const WithTabs = () => (
+  <Card title="Card title">
+    <Tabs
+      type="line"
+      style={{
+        marginTop: -20,
+        marginBottom: -20,
+      }}
+    >
+      <TabPane tab="Tab 1" itemKey="1">
+        <p>content1</p>
+        <p>content1</p>
+        <p>content1</p>
+      </TabPane>
+      <TabPane tab="Tab 2" itemKey="2">
+        <p>content2</p>
+        <p>content2</p>
+        <p>content2</p>
+      </TabPane>
+    </Tabs>
+  </Card>
+);
+
+export const Actions = () => (
+  <Space align="start">
+    <Card
+      style={{
+        width: 360,
+      }}
+      title={
+        <Meta
+          title="Semi Doc"
+          description="全面、易用、优质"
+          avatar={
+            <Avatar
+              size="default"
+              src="https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/card-meta-avatar-docs-demo.jpg"
+            />
+          }
+        />
+      }
+      actions={[<Rating defaultValue={4} />]}
+      headerLine={false}
+      footerLine={false}
+      footerStyle={{
+        display: 'flex',
+        justifyContent: 'flex-end',
+      }}
+      footer={
+        <Space>
+          <Button theme="solid" type="primary">
+            打分
+          </Button>
+        </Space>
+      }
+    >
+      Semi Design 是由互娱社区前端团队与 UED
+      团队共同设计开发并维护的设计系统。设计系统包含设计语言以及一整套可复用的前端组件,帮助设计师与开发者更容易地打造高质量的、用户体验一致的、符合设计规范的
+      Web 应用。
+    </Card>
+    <Card
+      style={{
+        width: 360,
+      }}
+      title={
+        <Meta
+          title="Semi Doc"
+          description="全面、易用、优质"
+          avatar={
+            <Avatar
+              size="default"
+              src="https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/card-meta-avatar-docs-demo.jpg"
+            />
+          }
+        />
+      }
+      actions={[<IconLikeThumb />, <IconLikeHeart />, <IconEdit />, <IconWrench />]}
+      headerLine={false}
+    >
+      Semi Design 是由互娱社区前端团队与 UED
+      团队共同设计开发并维护的设计系统。设计系统包含设计语言以及一整套可复用的前端组件,帮助设计师与开发者更容易地打造高质量的、用户体验一致的、符合设计规范的
+      Web 应用。
+    </Card>
+  </Space>
+);
+
+export const CardGroupDemo = () => (
+  <CardGroup spacing={12}>
+    {new Array(3).fill(null).map((v, idx) => (
+      <Card
+        key={idx}
+        style={{
+          width: 300,
+        }}
+        title={
+          <Meta
+            title="Semi Doc"
+            description="全面、易用、优质"
+            avatar={
+              <Avatar
+                size="default"
+                src="https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/card-meta-avatar-docs-demo.jpg"
+              />
+            }
+          />
+        }
+        headerExtraContent={<Text link>More</Text>}
+        cover={
+          <img
+            alt="example"
+            src="https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/card-cover-docs-demo.jpeg"
+          />
+        }
+      >
+        Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统。
+      </Card>
+    ))}
+  </CardGroup>
+);
+
+export const CardGroupGrid = () => (
+  <CardGroup type="grid">
+    {new Array(7).fill(null).map((v, idx) => (
+      <Card
+        key={idx}
+        shadows="hover"
+        title="Card title"
+        headerLine={false}
+        style={{
+          width: 260,
+        }}
+        headerExtraContent={<Text link>More</Text>}
+      >
+        <Text>Card content</Text>
+      </Card>
+    ))}
+  </CardGroup>
+);

+ 4 - 0
packages/semi-ui/cascader/_story/CustomTrigger/index.jsx

@@ -1,6 +1,10 @@
 import React from 'react';
 import { AutoComplete, Icon, Button, Cascader } from '@douyinfe/semi-ui';
 
+Demo.parameters = {
+    chromatic: { disableSnapshot: false },
+}
+
 export default function Demo() {
     const treeData = [
         {

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 557 - 535
packages/semi-ui/cascader/_story/cascader.stories.js


+ 899 - 764
packages/semi-ui/checkbox/_story/checkbox.stories.js

@@ -1,808 +1,943 @@
-import React, {useCallback, useMemo, useState} from 'react';
-import {storiesOf} from '@storybook/react'; // import { withKnobs, text, boolean } from '@storybook/addon-knobs';
+import React, { useCallback, useMemo, useState } from 'react';
 import Button from '../../button';
 import Popover from '../../popover';
 import Checkbox from '../index';
 import CheckboxGroup from '../checkboxGroup';
-import {Col, Input, Row} from '../../index';
-import {IconClose} from '@douyinfe/semi-icons';
+import { Col, Input, Row } from '../../index';
+import { IconClose } from '@douyinfe/semi-icons';
 
-const stories = storiesOf('Checkbox', module); // stories.addDecorator(withKnobs);;
+export default {
+  title: 'Checkbox',
+}
 
-stories.add('checkbox default', () => {
-    return (
-        <div>
-            <Checkbox onChange={e => console.log(e)} value={1} onChange={v => console.log(v)}>
-                hello
-            </Checkbox>
-            <br/>
-            <Checkbox checked>这是一个受控的checked=true的checkbox,没有配onChange</Checkbox>
-            <br/>
-            <Checkbox defaultChecked>这是一个不受控的defaultChecked=true的checkbox</Checkbox>
-            <br/>
-            <Checkbox disabled>这是一个受控的disabled=true的checkbox</Checkbox>
-            <br/>
-            <Checkbox checked disabled>
-                既checked又disabled
-            </Checkbox>
-            <br/>
-            <Checkbox indeterminate>indeterminate</Checkbox>
-        </div>
-    );
-});
-stories.add('checkbox without text', () => {
-    return (
-        <div>
-            <Checkbox onChange={e => console.log(e)}/>
-        </div>
-    );
-});
+export const CheckboxDefault = () => {
+  return (
+    <div>
+      <Checkbox onChange={e => console.log(e)} value={1} onChange={v => console.log(v)}>
+        hello
+      </Checkbox>
+      <br />
+      <Checkbox checked>这是一个受控的checked=true的checkbox,没有配onChange</Checkbox>
+      <br />
+      <Checkbox defaultChecked>这是一个不受控的defaultChecked=true的checkbox</Checkbox>
+      <br />
+      <Checkbox disabled>这是一个受控的disabled=true的checkbox</Checkbox>
+      <br />
+      <Checkbox checked disabled>
+        既checked又disabled
+      </Checkbox>
+      <br />
+      <Checkbox indeterminate>indeterminate</Checkbox>
+    </div>
+  );
+};
+
+export const CheckboxWithoutText = () => {
+  return (
+    <div>
+      <Checkbox onChange={e => console.log(e)} />
+    </div>
+  );
+};
 
 class CheckboxControl extends React.Component {
-    state = {
-        checked: true,
-        disabled: false,
-    };
-    toggleChecked = () => {
-        this.setState({
-            checked: !this.state.checked,
-        });
-    };
-    toggleDisable = () => {
-        this.setState({
-            disabled: !this.state.disabled,
-        });
-    };
-    onChange = e => {
-        console.log('checked = ', e.target.checked);
-        this.setState({
-            checked: e.target.checked,
-        });
-    };
+  state = {
+    checked: true,
+    disabled: false,
+  };
+  toggleChecked = () => {
+    this.setState({
+      checked: !this.state.checked,
+    });
+  };
+  toggleDisable = () => {
+    this.setState({
+      disabled: !this.state.disabled,
+    });
+  };
+  onChange = e => {
+    console.log('checked = ', e.target.checked);
+    this.setState({
+      checked: e.target.checked,
+    });
+  };
 
-    render() {
-        const label = `${this.state.checked ? 'Checked' : 'Unchecked'}-${this.state.disabled ? 'Disabled' : 'Enabled'}`;
-        return (
-            <div>
-                <p
-                    style={{
-                        marginBottom: '20px',
-                    }}
-                >
-                    <Checkbox checked={this.state.checked} disabled={this.state.disabled} onChange={this.onChange}>
-                        {label}
-                    </Checkbox>
-                </p>
-                <p>
-                    <Button type="primary" size="small" onClick={this.toggleChecked}>
-                        {!this.state.checked ? 'Check' : 'Uncheck'}
-                    </Button>
-                    <Button
-                        style={{
-                            marginLeft: '10px',
-                        }}
-                        type="primary"
-                        size="small"
-                        onClick={this.toggleDisable}
-                    >
-                        {!this.state.disabled ? 'Disable' : 'Enable'}
-                    </Button>
-                </p>
-            </div>
-        );
-    }
+  render() {
+    const label = `${this.state.checked ? 'Checked' : 'Unchecked'}-${
+      this.state.disabled ? 'Disabled' : 'Enabled'
+    }`;
+    return (
+      <div>
+        <p
+          style={{
+            marginBottom: '20px',
+          }}
+        >
+          <Checkbox
+            checked={this.state.checked}
+            disabled={this.state.disabled}
+            onChange={this.onChange}
+          >
+            {label}
+          </Checkbox>
+        </p>
+        <p>
+          <Button type="primary" size="small" onClick={this.toggleChecked}>
+            {!this.state.checked ? 'Check' : 'Uncheck'}
+          </Button>
+          <Button
+            style={{
+              marginLeft: '10px',
+            }}
+            type="primary"
+            size="small"
+            onClick={this.toggleDisable}
+          >
+            {!this.state.disabled ? 'Disable' : 'Enable'}
+          </Button>
+        </p>
+      </div>
+    );
+  }
 }
 
-stories.add('checkbox controlled disabled & checked', () => <CheckboxControl/>);
+export const CheckboxControlledDisabledChecked = () => <CheckboxControl />;
 
-class GroupDemo extends React.Component {
-    constructor() {
-        super();
-        this.state = {
-            value: [],
-        };
-        this.onChange = this.onChange.bind(this);
-    }
-
-    onChange(value) {
-        console.log(value);
-        this.setState({
-            value: value,
-        });
-    }
+CheckboxControlledDisabledChecked.story = {
+  name: 'checkbox controlled disabled & checked',
+};
 
-    render() {
-        let {value} = this.state;
-        return (
-            <>
-                水平Group
-                <Checkbox.Group direction="horizontal" onChange={v => console.log(v)}>
-                    <Checkbox value="dy">抖音</Checkbox>
-                    <Checkbox value="hotsoon">火山</Checkbox>
-                    <Checkbox value="toutiao">今日头条</Checkbox>
-                    <Checkbox value="xigua">西瓜视频</Checkbox>
-                </Checkbox.Group>
-                <br/>
-                <br/>
-                垂直Group
-                <Checkbox.Group onChange={v => console.log(v)}>
-                    <Checkbox value="dy">抖音</Checkbox>
-                    <Checkbox value="hotsoon">火山</Checkbox>
-                    <Checkbox value="toutiao">今日头条</Checkbox>
-                    <Checkbox value="xigua">西瓜视频</Checkbox>
-                </Checkbox.Group>
-                <br/>
-                <br/>
-                默认Group
-                <Checkbox.Group direction="horizontal" defaultValue={['xigua']} onChange={console.log}>
-                    <Checkbox value="dy">抖音</Checkbox>
-                    <Checkbox value="hotsoon">火山</Checkbox>
-                    <Checkbox value="toutiao">今日头条</Checkbox>
-                    <Checkbox value="xigua">西瓜视频</Checkbox>
-                </Checkbox.Group>
-                <br/>
-                <br/>
-                受控Group
-                <Checkbox.Group direction="horizontal" value={value} onChange={console.log}>
-                    <Checkbox value="dy">抖音</Checkbox>
-                    <Checkbox value="hotsoon">火山</Checkbox>
-                    <Checkbox value="toutiao">今日头条</Checkbox>
-                    <Checkbox value="xigua">西瓜视频</Checkbox>
-                </Checkbox.Group>
-                <br/>
-                <br/>
-                受控Group+onChange
-                <Checkbox.Group direction="horizontal" value={value} onChange={this.onChange}>
-                    <Checkbox value="dy">抖音</Checkbox>
-                    <Checkbox value="hotsoon">火山</Checkbox>
-                    <Checkbox value="toutiao">今日头条</Checkbox>
-                    <Checkbox value="xigua">西瓜视频</Checkbox>
-                </Checkbox.Group>
-                <br/>
-                <br/>
-                disabled
-                <Checkbox.Group disabled>
-                    <Checkbox value="dy">抖音</Checkbox>
-                    <Checkbox value="hotsoon">火山</Checkbox>
-                    <Checkbox value="toutiao">今日头条</Checkbox>
-                    <Checkbox value="xigua">西瓜视频</Checkbox>
-                </Checkbox.Group>
-            </>
-        );
-    }
-}
+class GroupDemo extends React.Component {
+  constructor() {
+    super();
+    this.state = {
+      value: [],
+    };
+    this.onChange = this.onChange.bind(this);
+  }
 
-stories.add('checkbox group', () => <GroupDemo/>);
-stories.add('checkbox group with options ', () => {
-    function onChange(checkedValues) {
-        console.log('checked = ', checkedValues);
-    }
+  onChange(value) {
+    console.log(value);
+    this.setState({
+      value: value,
+    });
+  }
 
-    const plainOptions = ['green', 'red', 'pink'];
-    const options = [
-        {
-            label: 'green',
-            value: 'green',
-        },
-        {
-            label: 'red',
-            value: 'red',
-        },
-        {
-            label: 'pink',
-            value: 'pink',
-            disabled: true,
-        },
-    ];
-    const optionsWithDisabled = [
-        {
-            label: 'green',
-            value: 'green',
-        },
-        {
-            label: 'red',
-            value: 'red',
-        },
-        {
-            label: 'pink',
-            value: 'pink',
-            disabled: false,
-        },
-    ];
-    return (
-        <div>
-            default
-            <CheckboxGroup options={plainOptions} defaultValue={['green']} onChange={onChange}/>
-            <br/>
-            <br/>
-            受控
-            <CheckboxGroup options={plainOptions} value={['green']} onChange={onChange}/>
-            <br/>
-            最后一个disabled
-            <br/>
-            <CheckboxGroup options={options} defaultValue={['red']} onChange={onChange}/>
-            <br/>
-            全体disabled, 优先父级disabled,次选子级disabled
-            <br/>
-            <CheckboxGroup options={optionsWithDisabled} disabled defaultValue={['green']} onChange={onChange}/>
-        </div>
-    );
-});
-stories.add('checkboxGroup-直接后代是其他类型Node', () => {
-    return (
-        <CheckboxGroup>
-            <div className="test">
-                <Checkbox value="green" extra="苹果">
-                    green
-                </Checkbox>
-                <Checkbox value="red" extra="梨">
-                    red
-                </Checkbox>
-                <Checkbox value="pink" extra="橙子">
-                    pink
-                </Checkbox>
-            </div>
-        </CheckboxGroup>
-    );
-});
-stories.add('checkbox 主文本+副文本', () => {
-    let options = [
-        {
-            label: 'green',
-            value: 'green',
-            extra: '苹果',
-        },
-        {
-            label: 'red',
-            value: 'red',
-            extra: '梨',
-        },
-        {
-            label: 'pink',
-            value: 'pink',
-            disabled: true,
-            extra: '橙子',
-        },
-    ];
-    return (
-        <div>
-            checkbox
-            <Checkbox
-                onChange={e => console.log(e)}
-                extra="我是副文本,这是辅助的文本,辅助文本会更长一些,甚至还可能换行"
-            >
-                我是主文本
-            </Checkbox>
-            <Checkbox
-                style={{
-                    width: 200,
-                }}
-                onChange={e => console.log(e)}
-                extra="我是副文本,这是辅助的文本,辅助文本会更长一些,甚至还可能换行"
-            >
-                我是主文本
-            </Checkbox>
-            <br/>
-            <br/>
-            checkboxGroup
-            <CheckboxGroup>
-                <Checkbox value="green" extra="苹果">
-                    green
-                </Checkbox>
-                <Checkbox value="red" extra="梨">
-                    red
-                </Checkbox>
-                <Checkbox value="pink" extra="橙子">
-                    pink
-                </Checkbox>
-            </CheckboxGroup>
-            <br/>
-            <br/>
-            checkboxGroup with options
-            <CheckboxGroup options={options}></CheckboxGroup>
-        </div>
-    );
-});
-stories.add('checkbox + grid', () => {
+  render() {
+    let { value } = this.state;
     return (
-        <Checkbox.Group
-            style={{
-                width: '100%',
-            }}
-            onChange={v => console.log(v)}
-        >
-            <Row>
-                <Col span={8}>
-                    <Checkbox value="A">
-                        无限长的一串字The Storybook webapp UI can be customised with this addon. It can be used to
-                        change the header, show/hide various UI elements and to enable full-screen mode by default.
-                    </Checkbox>
-                </Col>
-                <Col span={8}>
-                    <Checkbox value="B">B</Checkbox>
-                </Col>
-                <Col span={8}>
-                    <Checkbox value="C">C</Checkbox>
-                </Col>
-                <Col span={8}>
-                    <Checkbox value="D">D</Checkbox>
-                </Col>
-                <Col span={8}>
-                    <Checkbox value="E">E</Checkbox>
-                </Col>
-            </Row>
+      <>
+        水平Group
+        <Checkbox.Group direction="horizontal" onChange={v => console.log(v)}>
+          <Checkbox value="dy">抖音</Checkbox>
+          <Checkbox value="hotsoon">火山</Checkbox>
+          <Checkbox value="toutiao">今日头条</Checkbox>
+          <Checkbox value="xigua">西瓜视频</Checkbox>
+        </Checkbox.Group>
+        <br />
+        <br />
+        垂直Group
+        <Checkbox.Group onChange={v => console.log(v)}>
+          <Checkbox value="dy">抖音</Checkbox>
+          <Checkbox value="hotsoon">火山</Checkbox>
+          <Checkbox value="toutiao">今日头条</Checkbox>
+          <Checkbox value="xigua">西瓜视频</Checkbox>
+        </Checkbox.Group>
+        <br />
+        <br />
+        默认Group
+        <Checkbox.Group direction="horizontal" defaultValue={['xigua']} onChange={console.log}>
+          <Checkbox value="dy">抖音</Checkbox>
+          <Checkbox value="hotsoon">火山</Checkbox>
+          <Checkbox value="toutiao">今日头条</Checkbox>
+          <Checkbox value="xigua">西瓜视频</Checkbox>
+        </Checkbox.Group>
+        <br />
+        <br />
+        受控Group
+        <Checkbox.Group direction="horizontal" value={value} onChange={console.log}>
+          <Checkbox value="dy">抖音</Checkbox>
+          <Checkbox value="hotsoon">火山</Checkbox>
+          <Checkbox value="toutiao">今日头条</Checkbox>
+          <Checkbox value="xigua">西瓜视频</Checkbox>
+        </Checkbox.Group>
+        <br />
+        <br />
+        受控Group+onChange
+        <Checkbox.Group direction="horizontal" value={value} onChange={this.onChange}>
+          <Checkbox value="dy">抖音</Checkbox>
+          <Checkbox value="hotsoon">火山</Checkbox>
+          <Checkbox value="toutiao">今日头条</Checkbox>
+          <Checkbox value="xigua">西瓜视频</Checkbox>
         </Checkbox.Group>
+        <br />
+        <br />
+        disabled
+        <Checkbox.Group disabled>
+          <Checkbox value="dy">抖音</Checkbox>
+          <Checkbox value="hotsoon">火山</Checkbox>
+          <Checkbox value="toutiao">今日头条</Checkbox>
+          <Checkbox value="xigua">西瓜视频</Checkbox>
+        </Checkbox.Group>
+      </>
     );
-});
+  }
+}
 
+export const CheckboxGroupDemo = () => <GroupDemo />;
 
-const IndeterminateDemo = () => {
-    const options = ['yellow', 'green', 'red'];
-    const defaultCheckedColors = ['yellow', 'red'];
+export const CheckboxGroupWithOptions = () => {
+  function onChange(checkedValues) {
+    console.log('checked = ', checkedValues);
+  }
 
-    const [checkedList, setCheckList] = useState(defaultCheckedColors);
-    const [indeterminate, setIndeterminate] = useState(true);
-    const [checkAll, setCheckAll] = useState(false);
+  const plainOptions = ['green', 'red', 'pink'];
+  const options = [
+    {
+      label: 'green',
+      value: 'green',
+    },
+    {
+      label: 'red',
+      value: 'red',
+    },
+    {
+      label: 'pink',
+      value: 'pink',
+      disabled: true,
+    },
+  ];
+  const optionsWithDisabled = [
+    {
+      label: 'green',
+      value: 'green',
+    },
+    {
+      label: 'red',
+      value: 'red',
+    },
+    {
+      label: 'pink',
+      value: 'pink',
+      disabled: false,
+    },
+  ];
+  return (
+    <div>
+      default
+      <CheckboxGroup options={plainOptions} defaultValue={['green']} onChange={onChange} />
+      <br />
+      <br />
+      受控
+      <CheckboxGroup options={plainOptions} value={['green']} onChange={onChange} />
+      <br />
+      最后一个disabled
+      <br />
+      <CheckboxGroup options={options} defaultValue={['red']} onChange={onChange} />
+      <br />
+      全体disabled, 优先父级disabled,次选子级disabled
+      <br />
+      <CheckboxGroup
+        options={optionsWithDisabled}
+        disabled
+        defaultValue={['green']}
+        onChange={onChange}
+      />
+    </div>
+  );
+};
 
-    const onCheckListChange = checkedList => {
-        setCheckList([...checkedList]);
-        setIndeterminate(!!checkedList.length && checkedList.length < options.length);
-        setCheckAll(checkedList.length === options.length)
-    };
+export const CheckboxGroupWithOtherTypeChild = () => {
+  return (
+    <CheckboxGroup>
+      <div className="test">
+        <Checkbox value="green" extra="苹果">
+          green
+        </Checkbox>
+        <Checkbox value="red" extra="梨">
+          red
+        </Checkbox>
+        <Checkbox value="pink" extra="橙子">
+          pink
+        </Checkbox>
+      </div>
+    </CheckboxGroup>
+  );
+};
 
-    const onCheckAllChange = e => {
-        setCheckList([...(e.target.checked ? options : [])]);
-        setIndeterminate(false);
-        setCheckAll(e.target.checked)
-    };
+CheckboxGroupWithOtherTypeChild.story = {
+  name: 'checkboxGroup-直接后代是其他类型Node',
+};
 
+export const CheckboxExtra = () => {
+  let options = [
+    {
+      label: 'green',
+      value: 'green',
+      extra: '苹果',
+    },
+    {
+      label: 'red',
+      value: 'red',
+      extra: '梨',
+    },
+    {
+      label: 'pink',
+      value: 'pink',
+      disabled: true,
+      extra: '橙子',
+    },
+  ];
+  return (
+    <div>
+      checkbox
+      <Checkbox
+        onChange={e => console.log(e)}
+        extra="我是副文本,这是辅助的文本,辅助文本会更长一些,甚至还可能换行"
+      >
+        我是主文本
+      </Checkbox>
+      <Checkbox
+        style={{
+          width: 200,
+        }}
+        onChange={e => console.log(e)}
+        extra="我是副文本,这是辅助的文本,辅助文本会更长一些,甚至还可能换行"
+      >
+        我是主文本
+      </Checkbox>
+      <br />
+      <br />
+      checkboxGroup
+      <CheckboxGroup>
+        <Checkbox value="green" extra="苹果">
+          green
+        </Checkbox>
+        <Checkbox value="red" extra="梨">
+          red
+        </Checkbox>
+        <Checkbox value="pink" extra="橙子">
+          pink
+        </Checkbox>
+      </CheckboxGroup>
+      <br />
+      <br />
+      checkboxGroup with options
+      <CheckboxGroup options={options}></CheckboxGroup>
+    </div>
+  );
+};
 
-    return
-    return (
-        <div>
-            <div
-                style={{
-                    borderBottom: '1px solid #E9E9E9',
-                }}
-            >
-                <Checkbox
-                    indeterminate={indeterminate}
-                    onChange={onCheckAllChange}
-                    checked={state.checkAll}
-                >
-                    Check all
-                </Checkbox>
-            </div>
-            <br/>
-            <CheckboxGroup options={options} value={checkedList} onChange={onCheckListChange}/>
-        </div>
-    );
-}
+export const CheckboxGrid = () => {
+  return (
+    <Checkbox.Group
+      style={{
+        width: '100%',
+      }}
+      onChange={v => console.log(v)}
+    >
+      <Row>
+        <Col span={8}>
+          <Checkbox value="A">
+            无限长的一串字The Storybook webapp UI can be customised with this addon. It can be used
+            to change the header, show/hide various UI elements and to enable full-screen mode by
+            default.
+          </Checkbox>
+        </Col>
+        <Col span={8}>
+          <Checkbox value="B">B</Checkbox>
+        </Col>
+        <Col span={8}>
+          <Checkbox value="C">C</Checkbox>
+        </Col>
+        <Col span={8}>
+          <Checkbox value="D">D</Checkbox>
+        </Col>
+        <Col span={8}>
+          <Checkbox value="E">E</Checkbox>
+        </Col>
+      </Row>
+    </Checkbox.Group>
+  );
+};
 
+CheckboxGrid.story = {
+  name: 'checkbox + grid',
+};
 
-stories.add('checkbox inderterminate联动', () => <IndeterminateDemo/>);
-stories.add('checkbox render in div', () => (
-    <>
-        <div
-            onClick={(...args) => {
-                console.log('clicked checkbox outer: ', ...args);
-            }}
-        >
-            <Checkbox
-                onChange={(...args) => {
-                    console.log('clicked checkbox: ', ...args);
-                }}
-            />
-        </div>
-    </>
-));
-stories.add(`checkbox in popover`, () => (
+export const IndeterminateDemo = () => {
+  const options = ['yellow', 'green', 'red'];
+  const defaultCheckedColors = ['yellow', 'red'];
+
+  const [checkedList, setCheckList] = useState(defaultCheckedColors);
+  const [indeterminate, setIndeterminate] = useState(true);
+  const [checkAll, setCheckAll] = useState(false);
+
+  const onCheckListChange = checkedList => {
+    setCheckList([...checkedList]);
+    setIndeterminate(!!checkedList.length && checkedList.length < options.length);
+    setCheckAll(checkedList.length === options.length);
+  };
+
+  const onCheckAllChange = e => {
+    setCheckList([...(e.target.checked ? options : [])]);
+    setIndeterminate(false);
+    setCheckAll(e.target.checked);
+  };
+
+  return (
     <div>
-        <Popover
-            content={
-                <div>
-                    <Checkbox>选项一</Checkbox>
-                    <Checkbox defaultChecked>选项二</Checkbox>
-                    <Checkbox>选项三</Checkbox>
-                </div>
-            }
-        >
-            <Button>click me</Button>
-        </Popover>
+      <div
+        style={{
+          borderBottom: '1px solid #E9E9E9',
+        }}
+      >
+        <Checkbox indeterminate={indeterminate} onChange={onCheckAllChange} checked={checkAll}>
+          Check all
+        </Checkbox>
+      </div>
+      <br />
+      <CheckboxGroup options={options} value={checkedList} onChange={onCheckListChange} />
     </div>
-));
+  );
+};
+
+export const CheckboxRenderInDiv = () => (
+  <>
+    <div
+      onClick={(...args) => {
+        console.log('clicked checkbox outer: ', ...args);
+      }}
+    >
+      <Checkbox
+        onChange={(...args) => {
+          console.log('clicked checkbox: ', ...args);
+        }}
+      />
+    </div>
+  </>
+);
+
+export const CheckboxInPopover = () => (
+  <div>
+    <Popover
+      content={
+        <div>
+          <Checkbox>选项一</Checkbox>
+          <Checkbox defaultChecked>选项二</Checkbox>
+          <Checkbox>选项三</Checkbox>
+        </div>
+      }
+    >
+      <Button>click me</Button>
+    </Popover>
+  </div>
+)
 
 const SwitchCheckedFromTrue2Undefined = () => {
-    const [props, setProps] = useState();
-    const [flag, setFlag] = useState(0);
-
-    const change = () => {
-        if (flag === 0) {
-            setFlag(1);
-            setProps({checked: true});
-        } else {
-            setFlag(0);
-            setProps({checked: false});
-        }
-    };
+  const [props, setProps] = useState();
+  const [flag, setFlag] = useState(0);
 
-    return <>
-        <Checkbox {...props} >123</Checkbox>
-        <Button onClick={() => change()}>switch</Button>
+  const change = () => {
+    if (flag === 0) {
+      setFlag(1);
+      setProps({ checked: true });
+    } else {
+      setFlag(0);
+      setProps({ checked: false });
+    }
+  };
+
+  return (
+    <>
+      <Checkbox {...props}>123</Checkbox>
+      <Button onClick={() => change()}>switch</Button>
     </>
+  );
 };
 
-stories.add('checkbox switch checked: true => undefined', () => <SwitchCheckedFromTrue2Undefined/>);
+export const CheckboxSwitchCheckedTrueUndefined = () => <SwitchCheckedFromTrue2Undefined />;
+
+CheckboxSwitchCheckedTrueUndefined.story = {
+  name: 'checkbox switch checked: true => undefined',
+};
 
 const TransformSelect = props => {
-    const {onChange, value, options = [], defaultValue = [], placeholder} = props;
-    const [currentValue, setCurrentValue] = useState([]);
-    const [inputValue, setInputValue] = useState(''); // 变化
-
-    const onSelectChange = useCallback(() => {
-        setCurrentValue(currentValue);
-        onChange && onChange(currentValue);
-    }, []); // 选择某一个
-
-    const removeValue = useCallback(
-        currentIndex => {
-            currentValue.splice(currentIndex, 1);
-            onSelectChange([...currentValue]);
-        },
-        [currentValue]
-    ); // 选择所有
-
-    const selectAllValue = useCallback(() => {
-        const value = options.map(option => option.value);
-        onSelectChange(value);
-    }, [options]);
-    const viewsOptions = useMemo(() => {
-        if (inputValue) {
-            const newOptions = options.filter(option => option.label.indexOf(inputValue) !== -1);
-            return newOptions;
-        }
-
-        return options;
-    }, [options, inputValue]);
-    return (
+  const { onChange, value, options = [], defaultValue = [], placeholder } = props;
+  const [currentValue, setCurrentValue] = useState([]);
+  const [inputValue, setInputValue] = useState(''); // 变化
+
+  const onSelectChange = useCallback(() => {
+    setCurrentValue(currentValue);
+    onChange && onChange(currentValue);
+  }, []); // 选择某一个
+
+  const removeValue = useCallback(
+    currentIndex => {
+      currentValue.splice(currentIndex, 1);
+      onSelectChange([...currentValue]);
+    },
+    [currentValue]
+  ); // 选择所有
+
+  const selectAllValue = useCallback(() => {
+    const value = options.map(option => option.value);
+    onSelectChange(value);
+  }, [options]);
+  const viewsOptions = useMemo(() => {
+    if (inputValue) {
+      const newOptions = options.filter(option => option.label.indexOf(inputValue) !== -1);
+      return newOptions;
+    }
+
+    return options;
+  }, [options, inputValue]);
+  return (
+    <div>
+      <div>
         <div>
-            <div>
-                <div>
-                    <Input
-                        value={inputValue}
-                        prefix="search"
-                        clearable
-                        onChange={value => setInputValue(value)}
-                        placeholder={placeholder}
-                    />
-                </div>
-                <div>
-                    <span>{`共 ${options.length} 项`}</span>
-                    <Button type="tertiary" size="small" theme="borderless" onClick={() => selectAllValue()}>
-                        全选
-                    </Button>
-                </div>
-                <div>
-                    <CheckboxGroup
-                        options={viewsOptions}
-                        value={currentValue}
-                        onChange={onSelectChange}
-                        direction="vertical"
-                    />
-                </div>
-            </div>
-            <div>
-                <div>
-                    <span>{`已选 ${currentValue.length} 项`}</span>
-                    <Button type="tertiary" size="small" theme="borderless" onClick={() => onSelectChange([])}>
-                        清空
-                    </Button>
-                </div>
-                <div>
-                    {currentValue.length > 0 ? (
-                        currentValue.map((value, idx) => {
-                            // 不存在不需要展示
-                            const option = options.find(option => option.value === value);
-                            return (
-                                <div key={option.key ? option.key : idx}>
-                                    <span>{option.label}</span>
-                                    <span onClick={() => removeValue(idx)}>
-                                        <IconClose size="small"/>
-                                    </span>
-                                </div>
-                            );
-                        })
-                    ) : (
-                        <div>暂无内容,可从左侧勾选</div>
-                    )}
+          <Input
+            value={inputValue}
+            prefix="search"
+            clearable
+            onChange={value => setInputValue(value)}
+            placeholder={placeholder}
+          />
+        </div>
+        <div>
+          <span>{`共 ${options.length} 项`}</span>
+          <Button type="tertiary" size="small" theme="borderless" onClick={() => selectAllValue()}>
+            全选
+          </Button>
+        </div>
+        <div>
+          <CheckboxGroup
+            options={viewsOptions}
+            value={currentValue}
+            onChange={onSelectChange}
+            direction="vertical"
+          />
+        </div>
+      </div>
+      <div>
+        <div>
+          <span>{`已选 ${currentValue.length} 项`}</span>
+          <Button
+            type="tertiary"
+            size="small"
+            theme="borderless"
+            onClick={() => onSelectChange([])}
+          >
+            清空
+          </Button>
+        </div>
+        <div>
+          {currentValue.length > 0 ? (
+            currentValue.map((value, idx) => {
+              // 不存在不需要展示
+              const option = options.find(option => option.value === value);
+              return (
+                <div key={option.key ? option.key : idx}>
+                  <span>{option.label}</span>
+                  <span onClick={() => removeValue(idx)}>
+                    <IconClose size="small" />
+                  </span>
                 </div>
-            </div>
+              );
+            })
+          ) : (
+            <div>暂无内容,可从左侧勾选</div>
+          )}
         </div>
-    );
+      </div>
+    </div>
+  );
 };
 
-stories.add(`bugDemo`, () => <TransformSelect/>);
+export const BugDemo = () => <TransformSelect />;
 
-stories.add(`checkboxGroup card style`, () => (
-    <>
-        <div>常见情况</div>
-        <CheckboxGroup type='card' direction='horizontal' defaultValue={['1']}>
-            <Checkbox value='1' extra='Semi Design' style={{width: 280}}>
-                多选框标题
-            </Checkbox>
-            <Checkbox value='2' extra='Semi Design' style={{width: 280}}>
-                多选框标题
-            </Checkbox>
-            <Checkbox value='3' extra='Semi Design' style={{width: 280}}>
-                多选框标题
-            </Checkbox>
-        </CheckboxGroup>
-        <br/>
-        <br/>
-        <div>radio disabled</div>
-        <CheckboxGroup type='card' direction='horizontal' defaultValue={['1']}>
-            <Checkbox value='1' disabled extra='Semi Design' style={{width: 280}}>
-                多选框标题
-            </Checkbox>
-            <Checkbox value='2' extra='Semi Design' style={{width: 280}}>
-                多选框标题
-            </Checkbox>
-            <Checkbox value='3' extra='Semi Design' style={{width: 280}}>
-                多选框标题
-            </Checkbox>
-        </CheckboxGroup>
-        <br/>
-        <br/>
-        <div>checkboxGroup disabled</div>
-        <CheckboxGroup type='card' direction='horizontal' disabled defaultValue={['1']}>
-            <Checkbox value='1' extra='Semi Design' style={{width: 280}}>
-                多选框标题
-            </Checkbox>
-            <Checkbox value='2' extra='Semi Design' style={{width: 280}}>
-                多选框标题
-            </Checkbox>
-            <Checkbox value='3' extra='Semi Design' style={{width: 280}}>
-                多选框标题
-            </Checkbox>
-        </CheckboxGroup>
-        <br/>
-        <br/>
-        <div>文字很长,并且没有设置宽度,因此换行显示</div>
-        <CheckboxGroup type='card' direction='horizontal' defaultValue={['1']}>
-            <Checkbox value='1' extra='Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统'>
-                多选框标题
-            </Checkbox>
-            <Checkbox value='2' extra='Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统'>
-                多选框标题
-            </Checkbox>
-            <Checkbox value='3' extra='Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统'>
-                多选框标题
-            </Checkbox>
-        </CheckboxGroup>
-        <br/>
-        <br/>
-        <div>设置了width=180</div>
-        <CheckboxGroup type='card' direction='horizontal' defaultValue={['1']}>
-            <Checkbox value='1' extra='Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统' style={{width: 180}}>
-                多选框标题
-            </Checkbox>
-            <Checkbox value='2' extra='Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统' style={{width: 180}}>
-                多选框标题
-            </Checkbox>
-            <Checkbox value='3' extra='Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统' style={{width: 180}}>
-                多选框标题
-            </Checkbox>
-        </CheckboxGroup>
-        <br/>
-        <br/>
-        <div>没有extra,width=180</div>
-        <CheckboxGroup type='card' direction='horizontal' defaultValue={['1']}>
-            <Checkbox value='1' style={{width: 180}}>
-                多选框标题
-            </Checkbox>
-            <Checkbox value='2' style={{width: 180}}>
-                多选框标题
-            </Checkbox>
-            <Checkbox value='3' style={{width: 180}}>
-                多选框标题
-            </Checkbox>
-        </CheckboxGroup>
-        <br/>
-        <br/>
-        <div>没有标题,width=380</div>
-        <CheckboxGroup type='card' direction='horizontal' defaultValue={['1']}>
-            <Checkbox value='1' extra='Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统' style={{width: 380}}>
-            </Checkbox>
-            <Checkbox value='2' extra='Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统' style={{width: 380}}>
-            </Checkbox>
-            <Checkbox value='3' extra='Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统' style={{width: 380}}>
-            </Checkbox>
-        </CheckboxGroup>
-        <br/>
-        <br/>
-        <hr/>
-        <div>下面是垂直的情况:</div>
-        <div>常见情况</div>
-        <CheckboxGroup direction='vertical' type='card' defaultValue={['1']}>
-            <Checkbox value='1' extra='Semi Design' style={{width: 280}}>
-                多选框标题
-            </Checkbox>
-            <Checkbox value='2' extra='Semi Design' style={{width: 280}}>
-                多选框标题
-            </Checkbox>
-            <Checkbox value='3' extra='Semi Design' style={{width: 280}}>
-                多选框标题
-            </Checkbox>
-        </CheckboxGroup>
-        <br/>
-        <br/>
-        <div>没有设置宽度</div>
-        <CheckboxGroup direction='vertical' type='card' defaultValue={['1']}>
-            <Checkbox value='1' extra='Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统'>
-                多选框标题
-            </Checkbox>
-            <Checkbox value='2' extra='Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统'>
-                多选框标题
-            </Checkbox>
-            <Checkbox value='3' extra='Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统'>
-                多选框标题
-            </Checkbox>
-        </CheckboxGroup>
-        <br/>
-        <br/>
-        <div>设置了width=380</div>
-        <CheckboxGroup direction='vertical' type='card' defaultValue={['1']}>
-            <Checkbox value='1' extra='Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统' style={{width: 380}}>
-                多选框标题
-            </Checkbox>
-            <Checkbox value='2' extra='Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统' style={{width: 380}}>
-                多选框标题
-            </Checkbox>
-            <Checkbox value='3' extra='Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统' style={{width: 380}}>
-                多选框标题
-            </Checkbox>
-        </CheckboxGroup>
-    </>
-));
+export const CheckboxGroupCardStyle = () => (
+  <>
+    <div>常见情况</div>
+    <CheckboxGroup type="card" direction="horizontal" defaultValue={['1']}>
+      <Checkbox value="1" extra="Semi Design" style={{ width: 280 }}>
+        多选框标题
+      </Checkbox>
+      <Checkbox value="2" extra="Semi Design" style={{ width: 280 }}>
+        多选框标题
+      </Checkbox>
+      <Checkbox value="3" extra="Semi Design" style={{ width: 280 }}>
+        多选框标题
+      </Checkbox>
+    </CheckboxGroup>
+    <br />
+    <br />
+    <div>radio disabled</div>
+    <CheckboxGroup type="card" direction="horizontal" defaultValue={['1']}>
+      <Checkbox value="1" disabled extra="Semi Design" style={{ width: 280 }}>
+        多选框标题
+      </Checkbox>
+      <Checkbox value="2" extra="Semi Design" style={{ width: 280 }}>
+        多选框标题
+      </Checkbox>
+      <Checkbox value="3" extra="Semi Design" style={{ width: 280 }}>
+        多选框标题
+      </Checkbox>
+    </CheckboxGroup>
+    <br />
+    <br />
+    <div>checkboxGroup disabled</div>
+    <CheckboxGroup type="card" direction="horizontal" disabled defaultValue={['1']}>
+      <Checkbox value="1" extra="Semi Design" style={{ width: 280 }}>
+        多选框标题
+      </Checkbox>
+      <Checkbox value="2" extra="Semi Design" style={{ width: 280 }}>
+        多选框标题
+      </Checkbox>
+      <Checkbox value="3" extra="Semi Design" style={{ width: 280 }}>
+        多选框标题
+      </Checkbox>
+    </CheckboxGroup>
+    <br />
+    <br />
+    <div>文字很长,并且没有设置宽度,因此换行显示</div>
+    <CheckboxGroup type="card" direction="horizontal" defaultValue={['1']}>
+      <Checkbox
+        value="1"
+        extra="Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统"
+      >
+        多选框标题
+      </Checkbox>
+      <Checkbox
+        value="2"
+        extra="Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统"
+      >
+        多选框标题
+      </Checkbox>
+      <Checkbox
+        value="3"
+        extra="Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统"
+      >
+        多选框标题
+      </Checkbox>
+    </CheckboxGroup>
+    <br />
+    <br />
+    <div>设置了width=180</div>
+    <CheckboxGroup type="card" direction="horizontal" defaultValue={['1']}>
+      <Checkbox
+        value="1"
+        extra="Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统"
+        style={{ width: 180 }}
+      >
+        多选框标题
+      </Checkbox>
+      <Checkbox
+        value="2"
+        extra="Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统"
+        style={{ width: 180 }}
+      >
+        多选框标题
+      </Checkbox>
+      <Checkbox
+        value="3"
+        extra="Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统"
+        style={{ width: 180 }}
+      >
+        多选框标题
+      </Checkbox>
+    </CheckboxGroup>
+    <br />
+    <br />
+    <div>没有extra,width=180</div>
+    <CheckboxGroup type="card" direction="horizontal" defaultValue={['1']}>
+      <Checkbox value="1" style={{ width: 180 }}>
+        多选框标题
+      </Checkbox>
+      <Checkbox value="2" style={{ width: 180 }}>
+        多选框标题
+      </Checkbox>
+      <Checkbox value="3" style={{ width: 180 }}>
+        多选框标题
+      </Checkbox>
+    </CheckboxGroup>
+    <br />
+    <br />
+    <div>没有标题,width=380</div>
+    <CheckboxGroup type="card" direction="horizontal" defaultValue={['1']}>
+      <Checkbox
+        value="1"
+        extra="Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统"
+        style={{ width: 380 }}
+      ></Checkbox>
+      <Checkbox
+        value="2"
+        extra="Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统"
+        style={{ width: 380 }}
+      ></Checkbox>
+      <Checkbox
+        value="3"
+        extra="Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统"
+        style={{ width: 380 }}
+      ></Checkbox>
+    </CheckboxGroup>
+    <br />
+    <br />
+    <hr />
+    <div>下面是垂直的情况:</div>
+    <div>常见情况</div>
+    <CheckboxGroup direction="vertical" type="card" defaultValue={['1']}>
+      <Checkbox value="1" extra="Semi Design" style={{ width: 280 }}>
+        多选框标题
+      </Checkbox>
+      <Checkbox value="2" extra="Semi Design" style={{ width: 280 }}>
+        多选框标题
+      </Checkbox>
+      <Checkbox value="3" extra="Semi Design" style={{ width: 280 }}>
+        多选框标题
+      </Checkbox>
+    </CheckboxGroup>
+    <br />
+    <br />
+    <div>没有设置宽度</div>
+    <CheckboxGroup direction="vertical" type="card" defaultValue={['1']}>
+      <Checkbox
+        value="1"
+        extra="Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统"
+      >
+        多选框标题
+      </Checkbox>
+      <Checkbox
+        value="2"
+        extra="Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统"
+      >
+        多选框标题
+      </Checkbox>
+      <Checkbox
+        value="3"
+        extra="Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统"
+      >
+        多选框标题
+      </Checkbox>
+    </CheckboxGroup>
+    <br />
+    <br />
+    <div>设置了width=380</div>
+    <CheckboxGroup direction="vertical" type="card" defaultValue={['1']}>
+      <Checkbox
+        value="1"
+        extra="Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统"
+        style={{ width: 380 }}
+      >
+        多选框标题
+      </Checkbox>
+      <Checkbox
+        value="2"
+        extra="Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统"
+        style={{ width: 380 }}
+      >
+        多选框标题
+      </Checkbox>
+      <Checkbox
+        value="3"
+        extra="Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统"
+        style={{ width: 380 }}
+      >
+        多选框标题
+      </Checkbox>
+    </CheckboxGroup>
+  </>
+);
 
-stories.add(`checkboxGroup pureCard style`, () => (
-    <>
-        <div>常见情况</div>
-        <CheckboxGroup type='pureCard' defaultValue={['1']}>
-            <Checkbox value='1' extra='Semi Design' style={{width: 280}}>
-                多选框标题
-            </Checkbox>
-            <Checkbox value='2' extra='Semi Design' style={{width: 280}}>
-                多选框标题
-            </Checkbox>
-            <Checkbox value='3' extra='Semi Design' style={{width: 280}}>
-                多选框标题
-            </Checkbox>
-        </CheckboxGroup>
-        <br/>
-        <br/>
-        <div>radio disabled</div>
-        <CheckboxGroup type='pureCard' defaultValue={['1']}>
-            <Checkbox value='1' disabled extra='Semi Design' style={{width: 280}}>
-                多选框标题
-            </Checkbox>
-            <Checkbox value='2' extra='Semi Design' style={{width: 280}}>
-                多选框标题
-            </Checkbox>
-            <Checkbox value='3' extra='Semi Design' style={{width: 280}}>
-                多选框标题
-            </Checkbox>
-        </CheckboxGroup>
-        <br/>
-        <br/>
-        <div>checkboxGroup disabled</div>
-        <CheckboxGroup type='pureCard' disabled defaultValue={['1']}>
-            <Checkbox value='1' extra='Semi Design' style={{width: 280}}>
-                多选框标题
-            </Checkbox>
-            <Checkbox value='2' extra='Semi Design' style={{width: 280}}>
-                多选框标题
-            </Checkbox>
-            <Checkbox value='3' extra='Semi Design' style={{width: 280}}>
-                多选框标题
-            </Checkbox>
-        </CheckboxGroup>
-        <br/>
-        <br/>
-        <div>文字很长,并且没有设置宽度,因此换行显示</div>
-        <CheckboxGroup type='pureCard' defaultValue={['1']}>
-            <Checkbox value='1' extra='Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统'>
-                多选框标题
-            </Checkbox>
-            <Checkbox value='2' extra='Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统'>
-                多选框标题
-            </Checkbox>
-            <Checkbox value='3' extra='Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统'>
-                多选框标题
-            </Checkbox>
-        </CheckboxGroup>
-        <br/>
-        <br/>
-        <div>设置了width=180</div>
-        <CheckboxGroup type='pureCard' defaultValue={['1']}>
-            <Checkbox value='1' extra='Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统' style={{width: 180}}>
-                多选框标题
-            </Checkbox>
-            <Checkbox value='2' extra='Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统' style={{width: 180}}>
-                多选框标题
-            </Checkbox>
-            <Checkbox value='3' extra='Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统' style={{width: 180}}>
-                多选框标题
-            </Checkbox>
-        </CheckboxGroup>
-        <br/>
-        <br/>
-        <div>没有extra,width=180</div>
-        <CheckboxGroup type='pureCard' defaultValue={['1']}>
-            <Checkbox value='1' style={{width: 180}}>
-                多选框标题
-            </Checkbox>
-            <Checkbox value='2' style={{width: 180}}>
-                多选框标题
-            </Checkbox>
-            <Checkbox value='3' style={{width: 180}}>
-                多选框标题
-            </Checkbox>
-        </CheckboxGroup>
-        <br/>
-        <br/>
-        <div>没有标题,width=380</div>
-        <CheckboxGroup type='pureCard' defaultValue={['1']}>
-            <Checkbox value='1' extra='Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统' style={{width: 380}}>
-            </Checkbox>
-            <Checkbox value='2' extra='Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统' style={{width: 380}}>
-            </Checkbox>
-            <Checkbox value='3' extra='Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统' style={{width: 380}}>
-            </Checkbox>
-        </CheckboxGroup>
-        <br/>
-        <br/>
-        <hr/>
-        <div>下面是垂直的情况:</div>
-        <div>常见情况</div>
-        <CheckboxGroup direction='vertical' type='pureCard' defaultValue={['1']}>
-            <Checkbox value='1' extra='Semi Design' style={{width: 280}}>
-                多选框标题
-            </Checkbox>
-            <Checkbox value='2' extra='Semi Design' style={{width: 280}}>
-                多选框标题
-            </Checkbox>
-            <Checkbox value='3' extra='Semi Design' style={{width: 280}}>
-                多选框标题
-            </Checkbox>
-        </CheckboxGroup>
-        <br/>
-        <br/>
-        <div>没有设置宽度</div>
-        <CheckboxGroup direction='vertical' type='pureCard' defaultValue={['1']}>
-            <Checkbox value='1' extra='Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统'>
-                多选框标题
-            </Checkbox>
-            <Checkbox value='2' extra='Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统'>
-                多选框标题
-            </Checkbox>
-            <Checkbox value='3' extra='Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统'>
-                多选框标题
-            </Checkbox>
-        </CheckboxGroup>
-        <br/>
-        <br/>
-        <div>设置了width=380</div>
-        <CheckboxGroup direction='vertical' type='pureCard' defaultValue={['1']}>
-            <Checkbox value='1' extra='Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统' style={{width: 380}}>
-                多选框标题
-            </Checkbox>
-            <Checkbox value='2' extra='Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统' style={{width: 380}}>
-                多选框标题
-            </Checkbox>
-            <Checkbox value='3' extra='Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统' style={{width: 380}}>
-                多选框标题
-            </Checkbox>
-        </CheckboxGroup>
-    </>
-));
+export const CheckboxGroupPureCardStyle = () => (
+  <>
+    <div>常见情况</div>
+    <CheckboxGroup type="pureCard" defaultValue={['1']}>
+      <Checkbox value="1" extra="Semi Design" style={{ width: 280 }}>
+        多选框标题
+      </Checkbox>
+      <Checkbox value="2" extra="Semi Design" style={{ width: 280 }}>
+        多选框标题
+      </Checkbox>
+      <Checkbox value="3" extra="Semi Design" style={{ width: 280 }}>
+        多选框标题
+      </Checkbox>
+    </CheckboxGroup>
+    <br />
+    <br />
+    <div>radio disabled</div>
+    <CheckboxGroup type="pureCard" defaultValue={['1']}>
+      <Checkbox value="1" disabled extra="Semi Design" style={{ width: 280 }}>
+        多选框标题
+      </Checkbox>
+      <Checkbox value="2" extra="Semi Design" style={{ width: 280 }}>
+        多选框标题
+      </Checkbox>
+      <Checkbox value="3" extra="Semi Design" style={{ width: 280 }}>
+        多选框标题
+      </Checkbox>
+    </CheckboxGroup>
+    <br />
+    <br />
+    <div>checkboxGroup disabled</div>
+    <CheckboxGroup type="pureCard" disabled defaultValue={['1']}>
+      <Checkbox value="1" extra="Semi Design" style={{ width: 280 }}>
+        多选框标题
+      </Checkbox>
+      <Checkbox value="2" extra="Semi Design" style={{ width: 280 }}>
+        多选框标题
+      </Checkbox>
+      <Checkbox value="3" extra="Semi Design" style={{ width: 280 }}>
+        多选框标题
+      </Checkbox>
+    </CheckboxGroup>
+    <br />
+    <br />
+    <div>文字很长,并且没有设置宽度,因此换行显示</div>
+    <CheckboxGroup type="pureCard" defaultValue={['1']}>
+      <Checkbox
+        value="1"
+        extra="Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统"
+      >
+        多选框标题
+      </Checkbox>
+      <Checkbox
+        value="2"
+        extra="Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统"
+      >
+        多选框标题
+      </Checkbox>
+      <Checkbox
+        value="3"
+        extra="Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统"
+      >
+        多选框标题
+      </Checkbox>
+    </CheckboxGroup>
+    <br />
+    <br />
+    <div>设置了width=180</div>
+    <CheckboxGroup type="pureCard" defaultValue={['1']}>
+      <Checkbox
+        value="1"
+        extra="Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统"
+        style={{ width: 180 }}
+      >
+        多选框标题
+      </Checkbox>
+      <Checkbox
+        value="2"
+        extra="Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统"
+        style={{ width: 180 }}
+      >
+        多选框标题
+      </Checkbox>
+      <Checkbox
+        value="3"
+        extra="Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统"
+        style={{ width: 180 }}
+      >
+        多选框标题
+      </Checkbox>
+    </CheckboxGroup>
+    <br />
+    <br />
+    <div>没有extra,width=180</div>
+    <CheckboxGroup type="pureCard" defaultValue={['1']}>
+      <Checkbox value="1" style={{ width: 180 }}>
+        多选框标题
+      </Checkbox>
+      <Checkbox value="2" style={{ width: 180 }}>
+        多选框标题
+      </Checkbox>
+      <Checkbox value="3" style={{ width: 180 }}>
+        多选框标题
+      </Checkbox>
+    </CheckboxGroup>
+    <br />
+    <br />
+    <div>没有标题,width=380</div>
+    <CheckboxGroup type="pureCard" defaultValue={['1']}>
+      <Checkbox
+        value="1"
+        extra="Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统"
+        style={{ width: 380 }}
+      ></Checkbox>
+      <Checkbox
+        value="2"
+        extra="Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统"
+        style={{ width: 380 }}
+      ></Checkbox>
+      <Checkbox
+        value="3"
+        extra="Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统"
+        style={{ width: 380 }}
+      ></Checkbox>
+    </CheckboxGroup>
+    <br />
+    <br />
+    <hr />
+    <div>下面是垂直的情况:</div>
+    <div>常见情况</div>
+    <CheckboxGroup direction="vertical" type="pureCard" defaultValue={['1']}>
+      <Checkbox value="1" extra="Semi Design" style={{ width: 280 }}>
+        多选框标题
+      </Checkbox>
+      <Checkbox value="2" extra="Semi Design" style={{ width: 280 }}>
+        多选框标题
+      </Checkbox>
+      <Checkbox value="3" extra="Semi Design" style={{ width: 280 }}>
+        多选框标题
+      </Checkbox>
+    </CheckboxGroup>
+    <br />
+    <br />
+    <div>没有设置宽度</div>
+    <CheckboxGroup direction="vertical" type="pureCard" defaultValue={['1']}>
+      <Checkbox
+        value="1"
+        extra="Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统"
+      >
+        多选框标题
+      </Checkbox>
+      <Checkbox
+        value="2"
+        extra="Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统"
+      >
+        多选框标题
+      </Checkbox>
+      <Checkbox
+        value="3"
+        extra="Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统"
+      >
+        多选框标题
+      </Checkbox>
+    </CheckboxGroup>
+    <br />
+    <br />
+    <div>设置了width=380</div>
+    <CheckboxGroup direction="vertical" type="pureCard" defaultValue={['1']}>
+      <Checkbox
+        value="1"
+        extra="Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统"
+        style={{ width: 380 }}
+      >
+        多选框标题
+      </Checkbox>
+      <Checkbox
+        value="2"
+        extra="Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统"
+        style={{ width: 380 }}
+      >
+        多选框标题
+      </Checkbox>
+      <Checkbox
+        value="3"
+        extra="Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统"
+        style={{ width: 380 }}
+      >
+        多选框标题
+      </Checkbox>
+    </CheckboxGroup>
+  </>
+);

+ 121 - 116
packages/semi-ui/collapse/_story/accordion.stories.js

@@ -1,138 +1,143 @@
 import React from 'react';
-import { storiesOf } from '@storybook/react';
 import Collapse from '..';
 import { IconCopy } from '@douyinfe/semi-icons';
 
 const Panel = Collapse.Panel;
-const stories = storiesOf('Collapse', module);
+
 const text = `
   A dog is a type of domesticated animal.
   Known for its loyalty and faithfulness,
   it can be found:a welcome guest in many households across the world.
-`; // stories.addDecorator(withKnobs);;
+`;
+
+export default {
+  title: 'Collapse',
+}
+
+export const RegularCollapse = () => (
+  <div>
+    <Collapse onChange={k => console.log(k)}>
+      <Panel header="This is panel header 1" itemKey="1">
+        <p>{text}</p>
+      </Panel>
+      <Panel header="This is panel header 2" itemKey="2">
+        <p>{text}</p>
+      </Panel>
+      <Panel header="This is panel header 3" itemKey="3" disabled>
+        <p>{text}</p>
+      </Panel>
+    </Collapse>
+    <br />
+    <Collapse defaultActiveKey={'124'} onChange={k => console.log(k)}>
+      <Panel header="This is panel header 1" itemKey="1">
+        <p>{text}</p>
+      </Panel>
+      <Panel header="This is panel header 2" itemKey="124">
+        <p>{text}</p>
+      </Panel>
+      <Panel header="This is panel header 3" itemKey="3" disabled>
+        <p>{text}</p>
+      </Panel>
+    </Collapse>
+  </div>
+);
+
+export const Accordion = () => (
+  <div>
+    <Collapse defaultActiveKey={'123'} accordion onChange={k => console.log(k)}>
+      <Panel header="This is panel header 1" itemKey="123">
+        <p>{text}</p>
+      </Panel>
+      <Panel header="This is panel header 2" itemKey="234">
+        <p>{text}</p>
+      </Panel>
+      <Panel header="This is panel header 3" itemKey="3" disabled>
+        <p>{text}</p>
+      </Panel>
+    </Collapse>
+  </div>
+);
 
-stories.add('regular collapse', () => (
-    <div>
-        <Collapse onChange={k => console.log(k)}>
-            <Panel header="This is panel header 1" itemKey="1">
-                <p>{text}</p>
-            </Panel>
-            <Panel header="This is panel header 2" itemKey="2">
-                <p>{text}</p>
-            </Panel>
-            <Panel header="This is panel header 3" itemKey="3" disabled>
-                <p>{text}</p>
-            </Panel>
-        </Collapse>
-        <br />
-        <Collapse defaultActiveKey={'124'} onChange={k => console.log(k)}>
-            <Panel header="This is panel header 1" itemKey="1">
-                <p>{text}</p>
-            </Panel>
-            <Panel header="This is panel header 2" itemKey="124">
-                <p>{text}</p>
-            </Panel>
-            <Panel header="This is panel header 3" itemKey="3" disabled>
-                <p>{text}</p>
-            </Panel>
-        </Collapse>
-    </div>
-));
-stories.add('accordion', () => (
-    <div>
-        <Collapse defaultActiveKey={'123'} accordion onChange={k => console.log(k)}>
-            <Panel header="This is panel header 1" itemKey="123">
-                <p>{text}</p>
-            </Panel>
-            <Panel header="This is panel header 2" itemKey="234">
-                <p>{text}</p>
-            </Panel>
-            <Panel header="This is panel header 3" itemKey="3" disabled>
-                <p>{text}</p>
-            </Panel>
-        </Collapse>
-    </div>
-));
-stories.add('extra rendering', () => (
-    <div>
-        <Collapse activeKey={'123'} onChange={k => console.log(k)}>
-            <Panel header="This is panel header 1" itemKey="123" extra="1234">
-                <p>{text}</p>
-            </Panel>
-            <Panel header="This is panel header 2" itemKey="2" extra={<IconCopy />}>
-                <p>{text}</p>
-            </Panel>
-            <Panel header="This is panel header 3" itemKey="3" disabled>
-                <p>{text}</p>
-            </Panel>
-        </Collapse>
-    </div>
-));
+export const ExtraRendering = () => (
+  <div>
+    <Collapse activeKey={'123'} onChange={k => console.log(k)}>
+      <Panel header="This is panel header 1" itemKey="123" extra="1234">
+        <p>{text}</p>
+      </Panel>
+      <Panel header="This is panel header 2" itemKey="2" extra={<IconCopy />}>
+        <p>{text}</p>
+      </Panel>
+      <Panel header="This is panel header 3" itemKey="3" disabled>
+        <p>{text}</p>
+      </Panel>
+    </Collapse>
+  </div>
+);
 
 class ControlledDemo extends React.Component {
-    constructor() {
-        super();
-        this.state = {
-            value: [],
-        };
-    }
+  constructor() {
+    super();
+    this.state = {
+      value: [],
+    };
+  }
 
-    onChange(value) {
-        console.log(value);
-        this.setState({
-            value,
-        });
-    }
+  onChange(value) {
+    console.log(value);
+    this.setState({
+      value,
+    });
+  }
 
-    render() {
-        return (
-            <Collapse activeKey={this.state.value} onChange={k => this.onChange(k)}>
-                <Panel header="This is panel header 1" itemKey="123" extra="1234">
-                    <p>{text}</p>
-                </Panel>
-                <Panel header="This is panel header 2" itemKey="2" extra={<IconCopy />}>
-                    <p>{text}</p>
-                </Panel>
-                <Panel header="This is panel header 3" itemKey="3" disabled>
-                    <p>{text}</p>
-                </Panel>
-            </Collapse>
-        );
-    }
+  render() {
+    return (
+      <Collapse activeKey={this.state.value} onChange={k => this.onChange(k)}>
+        <Panel header="This is panel header 1" itemKey="123" extra="1234">
+          <p>{text}</p>
+        </Panel>
+        <Panel header="This is panel header 2" itemKey="2" extra={<IconCopy />}>
+          <p>{text}</p>
+        </Panel>
+        <Panel header="This is panel header 3" itemKey="3" disabled>
+          <p>{text}</p>
+        </Panel>
+      </Collapse>
+    );
+  }
 }
 
-stories.add('controlled component', () => <ControlledDemo />);
+export const ControlledComponent = () => <ControlledDemo />;
 
 class ControlledDemoAccordion extends React.Component {
-    constructor() {
-        super();
-        this.state = {
-            value: [],
-        };
-    }
+  constructor() {
+    super();
+    this.state = {
+      value: [],
+    };
+  }
 
-    onChange(value) {
-        console.log(value);
-        this.setState({
-            value,
-        });
-    }
+  onChange(value) {
+    console.log(value);
+    this.setState({
+      value,
+    });
+  }
 
-    render() {
-        return (
-            <Collapse activeKey={this.state.value} accordion onChange={k => this.onChange(k)}>
-                <Panel header="This is panel header 1" itemKey="123" extra="1234">
-                    <p>{text}</p>
-                </Panel>
-                <Panel header="This is panel header 2" itemKey="2" extra={<IconCopy />}>
-                    <p>{text}</p>
-                </Panel>
-                <Panel header="This is panel header 3" itemKey="3" disabled>
-                    <p>{text}</p>
-                </Panel>
-            </Collapse>
-        );
-    }
+  render() {
+    return (
+      <Collapse activeKey={this.state.value} accordion onChange={k => this.onChange(k)}>
+        <Panel header="This is panel header 1" itemKey="123" extra="1234">
+          <p>{text}</p>
+        </Panel>
+        <Panel header="This is panel header 2" itemKey="2" extra={<IconCopy />}>
+          <p>{text}</p>
+        </Panel>
+        <Panel header="This is panel header 3" itemKey="3" disabled>
+          <p>{text}</p>
+        </Panel>
+      </Collapse>
+    );
+  }
 }
 
-stories.add('controlled component accordion', () => <ControlledDemoAccordion />);
+export const ControlledComponentAccordion = () => <ControlledDemoAccordion />;

+ 524 - 510
packages/semi-ui/collapsible/_story/collapsible.stories.js

@@ -1,574 +1,588 @@
 /* argus-disable unPkgSensitiveInfo */
 import React, { useState } from 'react';
-import { storiesOf } from '@storybook/react';
 import { Button, CheckboxGroup, Upload, Table, Collapse, Tabs } from '../../index';
 import Collapsible from '..';
 import NestedDemo from './Nested';
 import { IconChevronDown, IconChevronRight, IconUpload } from '@douyinfe/semi-icons';
 
 const TabPane = Tabs.TabPane;
-const stories = storiesOf('Collapsible', module); // stories.addDecorator(withKnobs);;
 
-class Demo extends React.Component {
-    state = {
-        isOpen: false,
-    };
-    toggle = () => {
-        this.setState({
-            isOpen: !this.state.isOpen,
-        });
-    };
+export default {
+  title: 'Collapsible',
+}
 
-    render() {
-        const { isOpen } = this.state;
-        const collapsed = (
-            <ul>
-                <li>
-                    <p>Semi Design 以内容优先进行设计。</p>
-                </li>
-                <li>
-                    <p>更容易地自定义主题。</p>
-                </li>
-                <li>
-                    <p>适用国际化场景。</p>
-                </li>
-                <li>
-                    <p>效率场景加入人性化关怀。</p>
-                </li>
-            </ul>
-        );
-        return (
-            <div>
-                <Button onClick={() => this.toggle()}>显示更多</Button>
-                <Collapsible isOpen={isOpen}>{collapsed}</Collapsible>
-            </div>
-        );
-    }
+class Demo extends React.Component {
+  state = {
+    isOpen: false,
+  };
+  toggle = () => {
+    this.setState({
+      isOpen: !this.state.isOpen,
+    });
+  };
+
+  render() {
+    const { isOpen } = this.state;
+    const collapsed = (
+      <ul>
+        <li>
+          <p>Semi Design 以内容优先进行设计。</p>
+        </li>
+        <li>
+          <p>更容易地自定义主题。</p>
+        </li>
+        <li>
+          <p>适用国际化场景。</p>
+        </li>
+        <li>
+          <p>效率场景加入人性化关怀。</p>
+        </li>
+      </ul>
+    );
+    return (
+      <div>
+        <Button onClick={() => this.toggle()}>显示更多</Button>
+        <Collapsible isOpen={isOpen}>{collapsed}</Collapsible>
+      </div>
+    );
+  }
 }
 
-stories.add('regular collapsible', () => <Demo />);
+export const RegularCollapsible = () => <Demo />;
 
 class DemoDOM extends React.Component {
-    state = {
-        isOpen: false,
-    };
-    toggle = () => {
-        this.setState({
-            isOpen: !this.state.isOpen,
-        });
-    };
-
-    render() {
-        const { isOpen } = this.state;
-        const collapsed = (
-            <ul>
-                <li>
-                    <p>Semi Design 以内容优先进行设计。</p>
-                </li>
-                <li>
-                    <p>更容易地自定义主题。</p>
-                </li>
-                <li>
-                    <p>适用国际化场景。</p>
-                </li>
-                <li>
-                    <p>效率场景加入人性化关怀。</p>
-                </li>
-            </ul>
-        );
-        return (
-            <div>
-                <Button onClick={() => this.toggle()}>显示更多</Button>
-                <Collapsible keepDOM isOpen={isOpen}>
-                    {collapsed}
-                </Collapsible>
-            </div>
-        );
-    }
+  state = {
+    isOpen: false,
+  };
+  toggle = () => {
+    this.setState({
+      isOpen: !this.state.isOpen,
+    });
+  };
+
+  render() {
+    const { isOpen } = this.state;
+    const collapsed = (
+      <ul>
+        <li>
+          <p>Semi Design 以内容优先进行设计。</p>
+        </li>
+        <li>
+          <p>更容易地自定义主题。</p>
+        </li>
+        <li>
+          <p>适用国际化场景。</p>
+        </li>
+        <li>
+          <p>效率场景加入人性化关怀。</p>
+        </li>
+      </ul>
+    );
+    return (
+      <div>
+        <Button onClick={() => this.toggle()}>显示更多</Button>
+        <Collapsible keepDOM isOpen={isOpen}>
+          {collapsed}
+        </Collapsible>
+      </div>
+    );
+  }
 }
 
-stories.add('keepDOM', () => <DemoDOM />);
-
-class DefaultOPen extends React.Component {
-    state = {
-        isOpen: true,
-    };
-    toggle = () => {
-        this.setState({
-            isOpen: !this.state.isOpen,
-        });
-    };
-
-    render() {
-        const { isOpen } = this.state;
-        const collapsed = (
-            <ul>
-                <li>
-                    <p>Semi Design 以内容优先进行设计。</p>
-                </li>
-                <li>
-                    <p>更容易地自定义主题。</p>
-                </li>
-                <li>
-                    <p>适用国际化场景。</p>
-                </li>
-                <li>
-                    <p>效率场景加入人性化关怀。</p>
-                </li>
-            </ul>
-        );
-        return (
-            <div>
-                <Button onClick={() => this.toggle()}>toggle</Button>
-                <Collapsible isOpen={isOpen}>{collapsed}</Collapsible>
-            </div>
-        );
-    }
+export const KeepDom = () => <DemoDOM />;
+
+class DefaultOpen extends React.Component {
+  state = {
+    isOpen: true,
+  };
+  toggle = () => {
+    this.setState({
+      isOpen: !this.state.isOpen,
+    });
+  };
+
+  render() {
+    const { isOpen } = this.state;
+    const collapsed = (
+      <ul>
+        <li>
+          <p>Semi Design 以内容优先进行设计。</p>
+        </li>
+        <li>
+          <p>更容易地自定义主题。</p>
+        </li>
+        <li>
+          <p>适用国际化场景。</p>
+        </li>
+        <li>
+          <p>效率场景加入人性化关怀。</p>
+        </li>
+      </ul>
+    );
+    return (
+      <div>
+        <Button onClick={() => this.toggle()}>toggle</Button>
+        <Collapsible isOpen={isOpen}>{collapsed}</Collapsible>
+      </div>
+    );
+  }
 }
 
-stories.add('Default Open', () => <DefaultOPen />);
-stories.add('nested collapsible', () => <NestedDemo />);
+export const DefaultOpenDemo = () => <DefaultOpen />;
+export const NestedCollapsible = () => <NestedDemo />;
 
 class Wrap extends React.Component {
-    constructor(props) {
-        super(props);
-        this.state = {
-            isOpen: props.isOpen,
-            options: [
-                {
-                    label: '抖音',
-                    value: 'dy',
-                },
-                {
-                    label: '火山',
-                    value: 'hotsoon',
-                },
-                {
-                    label: '皮皮虾',
-                    value: 'pipixia',
-                },
-                {
-                    label: '今日头条',
-                    value: 'toutiao',
-                },
-            ],
-            values: [],
-        };
-        this.toggle = this.toggle.bind(this);
-        this.onChange = this.onChange.bind(this);
-    }
-
-    toggle() {
-        this.setState({
-            isOpen: !this.state.isOpen,
-        });
-    }
-
-    onChange(values) {
-        this.setState({
-            values,
-        });
-    }
-
-    render() {
-        const { isOpen, options, values } = this.state;
-        return (
-            <>
-                <div onClick={this.toggle}>
-                    {isOpen ? <IconChevronDown /> : <IconChevronRight />}
-                    权限点
-                    <span>
-                        {values.length}/{options.length}
-                    </span>
-                </div>
-                <Collapse defaultActiveKey="1" motion={false}>
-                    <Collapse.Panel header="This is panel header 1" itemKey="1">
-                        <p>Hi, bytedance dance dance. This is the docsite of Semi UI. </p>
-                    </Collapse.Panel>
-                    <Collapse.Panel header="This is panel header 2" itemKey="2">
-                        <p>Hi, bytedance dance dance. This is the docsite of Semi UI. </p>
-                    </Collapse.Panel>
-                    <Collapse.Panel header="This is panel header 3" itemKey="3">
-                        <p>Hi, bytedance dance dance. This is the docsite of Semi UI. </p>
-                    </Collapse.Panel>
-                </Collapse>
-                {/* <Collapsible isOpen={isOpen}>
+  constructor(props) {
+    super(props);
+    this.state = {
+      isOpen: props.isOpen,
+      options: [
+        {
+          label: '抖音',
+          value: 'dy',
+        },
+        {
+          label: '火山',
+          value: 'hotsoon',
+        },
+        {
+          label: '皮皮虾',
+          value: 'pipixia',
+        },
+        {
+          label: '今日头条',
+          value: 'toutiao',
+        },
+      ],
+      values: [],
+    };
+    this.toggle = this.toggle.bind(this);
+    this.onChange = this.onChange.bind(this);
+  }
+
+  toggle() {
+    this.setState({
+      isOpen: !this.state.isOpen,
+    });
+  }
+
+  onChange(values) {
+    this.setState({
+      values,
+    });
+  }
+
+  render() {
+    const { isOpen, options, values } = this.state;
+    return (
+      <>
+        <div onClick={this.toggle}>
+          {isOpen ? <IconChevronDown /> : <IconChevronRight />}
+          权限点
+          <span>
+            {values.length}/{options.length}
+          </span>
+        </div>
+        <Collapse defaultActiveKey="1" motion={false}>
+          <Collapse.Panel header="This is panel header 1" itemKey="1">
+            <p>Hi, bytedance dance dance. This is the docsite of Semi UI. </p>
+          </Collapse.Panel>
+          <Collapse.Panel header="This is panel header 2" itemKey="2">
+            <p>Hi, bytedance dance dance. This is the docsite of Semi UI. </p>
+          </Collapse.Panel>
+          <Collapse.Panel header="This is panel header 3" itemKey="3">
+            <p>Hi, bytedance dance dance. This is the docsite of Semi UI. </p>
+          </Collapse.Panel>
+        </Collapse>
+        {/* <Collapsible isOpen={isOpen}>
            <div style={{ height: '40px' }}>
                <CheckboxGroup options={options} direction="horizontal" onChange={this.onChange} value={values} />
            </div>
         </Collapsible> */}
-            </>
-        );
-    }
+      </>
+    );
+  }
 }
 
-stories.add('collapsible test', () => <Wrap />);
+export const CollapsibleTest = () => <Wrap />;
 
 class App extends React.Component {
-    render() {
-        const expandColumns = [
-            {
-                title: 'Name',
-                dataIndex: 'name',
-                key: 'name',
-            },
-            {
-                title: 'Age',
-                dataIndex: 'age',
-                key: 'age',
-            },
-            {
-                title: 'Address',
-                dataIndex: 'address',
-                key: 'address',
-            },
-            {
-                title: 'Action',
-                dataIndex: '',
-                key: 'x',
-                render: () => <a>Delete</a>,
-            },
-        ];
-        const rowSelection = {
-            onChange: (selectedRowKeys, selectedRows) => {
-                // console.log(`selectedRowKeys: ${selectedRowKeys}`, 'selectedRows: ', selectedRows);
-            },
-            getCheckboxProps: record => ({
-                disabled: record.name === 'Michael James',
-                // Column configuration not to be checked
-                name: record.name,
-            }),
-        };
-        const expandData = [
-            {
-                name: 'John Brown',
-                age: 32,
-                address: 'New York No. 1 Lake Park',
-                description: 'My name is John Brown, I am 32 years old, living in New York No. 1 Lake Park.',
-            },
-            {
-                name: 'Jim Green',
-                age: 42,
-                address: 'London No. 1 Lake Park',
-                description: 'My name is Jim Green, I am 42 years old, living in London No. 1 Lake Park.',
-            },
-            {
-                name: 'Joe Black',
-                age: 32,
-                address: (
-                    <Collapse defaultActiveKey="1" motion={false}>
-                        <Collapse.Panel header="This is panel header 1" itemKey="1">
-                            <p>Hi, bytedance dance dance. This is the docsite of Semi UI. </p>
-                        </Collapse.Panel>
-                        <Collapse.Panel header="This is panel header 2" itemKey="2">
-                            <p>Hi, bytedance dance dance. This is the docsite of Semi UI. </p>
-                        </Collapse.Panel>
-                        <Collapse.Panel header="This is panel header 3" itemKey="3">
-                            <p>Hi, bytedance dance dance. This is the docsite of Semi UI. </p>
-                        </Collapse.Panel>
-                    </Collapse>
-                ),
-                description: 'My name is Joe Black, I am 32 years old, living in Sidney No. 1 Lake Park.',
-            },
-        ];
-
-        const expandRowRender = (record, index) => <Wrap isOpen={true} />;
-
-        return (
-            <Table
-                rowKey={'name'}
-                columns={expandColumns}
-                rowSelection={rowSelection}
-                expandedRowRender={expandRowRender}
-                dataSource={expandData}
-            />
-        );
-    }
+  render() {
+    const expandColumns = [
+      {
+        title: 'Name',
+        dataIndex: 'name',
+        key: 'name',
+      },
+      {
+        title: 'Age',
+        dataIndex: 'age',
+        key: 'age',
+      },
+      {
+        title: 'Address',
+        dataIndex: 'address',
+        key: 'address',
+      },
+      {
+        title: 'Action',
+        dataIndex: '',
+        key: 'x',
+        render: () => <a>Delete</a>,
+      },
+    ];
+    const rowSelection = {
+      onChange: (selectedRowKeys, selectedRows) => {
+        // console.log(`selectedRowKeys: ${selectedRowKeys}`, 'selectedRows: ', selectedRows);
+      },
+      getCheckboxProps: record => ({
+        disabled: record.name === 'Michael James',
+        // Column configuration not to be checked
+        name: record.name,
+      }),
+    };
+    const expandData = [
+      {
+        name: 'John Brown',
+        age: 32,
+        address: 'New York No. 1 Lake Park',
+        description:
+          'My name is John Brown, I am 32 years old, living in New York No. 1 Lake Park.',
+      },
+      {
+        name: 'Jim Green',
+        age: 42,
+        address: 'London No. 1 Lake Park',
+        description: 'My name is Jim Green, I am 42 years old, living in London No. 1 Lake Park.',
+      },
+      {
+        name: 'Joe Black',
+        age: 32,
+        address: (
+          <Collapse defaultActiveKey="1" motion={false}>
+            <Collapse.Panel header="This is panel header 1" itemKey="1">
+              <p>Hi, bytedance dance dance. This is the docsite of Semi UI. </p>
+            </Collapse.Panel>
+            <Collapse.Panel header="This is panel header 2" itemKey="2">
+              <p>Hi, bytedance dance dance. This is the docsite of Semi UI. </p>
+            </Collapse.Panel>
+            <Collapse.Panel header="This is panel header 3" itemKey="3">
+              <p>Hi, bytedance dance dance. This is the docsite of Semi UI. </p>
+            </Collapse.Panel>
+          </Collapse>
+        ),
+        description: 'My name is Joe Black, I am 32 years old, living in Sidney No. 1 Lake Park.',
+      },
+    ];
+
+    const expandRowRender = (record, index) => <Wrap isOpen={true} />;
+
+    return (
+      <Table
+        rowKey={'name'}
+        columns={expandColumns}
+        rowSelection={rowSelection}
+        expandedRowRender={expandRowRender}
+        dataSource={expandData}
+      />
+    );
+  }
 }
 
-stories.add('collapsible in table', () => <App />);
+export const CollapsibleInTable = () => <App />;
 
 class InTab extends React.Component {
-    constructor() {
-        super();
-        this.state = {
-            isOpenFirst: false,
-            isOpenSecond: false,
-        };
-    }
-
-    render() {
-        const { isOpenFirst, isOpenSecond } = this.state;
-        return (
-            <div>
-                <Tabs
-                    onTabClick={e =>
-                        this.setState({
-                            active: e,
-                        })
-                    }
-                >
-                    <TabPane tab="第一" itemKey="1">
-                        <h3>第一个tabpane</h3>
-                        <Button
-                            onClick={() => {
-                                this.setState({
-                                    isOpenFirst: !isOpenFirst,
-                                });
-                            }}
-                        >
-                            开关
-                        </Button>
-                        <Collapsible isOpen={isOpenFirst}>第一个tabpane下的collapsible的open状态正常</Collapsible>
-                    </TabPane>
-                    <TabPane tab="第二" itemKey="2">
-                        <h3>第二个tabpane</h3>
-                        <Button
-                            onClick={() => {
-                                this.setState({
-                                    isOpenSecond: !isOpenSecond,
-                                });
-                            }}
-                        >
-                            开关
-                        </Button>
-                        <Collapsible isOpen={isOpenSecond}>第二个tabpane下的collapsibleopen状态异常</Collapsible>
-                    </TabPane>
-                </Tabs>
-            </div>
-        );
-    }
+  constructor() {
+    super();
+    this.state = {
+      isOpenFirst: false,
+      isOpenSecond: false,
+    };
+  }
+
+  render() {
+    const { isOpenFirst, isOpenSecond } = this.state;
+    return (
+      <div>
+        <Tabs
+          onTabClick={e =>
+            this.setState({
+              active: e,
+            })
+          }
+        >
+          <TabPane tab="第一" itemKey="1">
+            <h3>第一个tabpane</h3>
+            <Button
+              onClick={() => {
+                this.setState({
+                  isOpenFirst: !isOpenFirst,
+                });
+              }}
+            >
+              开关
+            </Button>
+            <Collapsible isOpen={isOpenFirst}>
+              第一个tabpane下的collapsible的open状态正常
+            </Collapsible>
+          </TabPane>
+          <TabPane tab="第二" itemKey="2">
+            <h3>第二个tabpane</h3>
+            <Button
+              onClick={() => {
+                this.setState({
+                  isOpenSecond: !isOpenSecond,
+                });
+              }}
+            >
+              开关
+            </Button>
+            <Collapsible isOpen={isOpenSecond}>
+              第二个tabpane下的collapsibleopen状态异常
+            </Collapsible>
+          </TabPane>
+        </Tabs>
+      </div>
+    );
+  }
 }
 
-stories.add('collapsible in tab', () => <InTab />);
+export const CollapsibleInTab = () => <InTab />;
+
+CollapsibleInTab.story = {
+  name: 'collapsible in tab',
+};
 
 class WithUpload extends React.Component {
-    constructor(props) {
-        super(props);
-        this.state = {
-            isOpen: true,
-        };
-        this.toggle = this.toggle.bind(this);
-        this.action = '//semi.design/api/upload/';
-        this.defaultFileList = [
-            {
+  constructor(props) {
+    super(props);
+    this.state = {
+      isOpen: true,
+    };
+    this.toggle = this.toggle.bind(this);
+    this.action = '//semi.design/api/upload/';
+    this.defaultFileList = [
+      {
+        preview: false,
+        name: '2D (2).ecpj',
+        status: 'success',
+        uid: 'd116a179410eb0ca18e66074509bde93-0',
+        url:
+          'https://sf6-cdn-tos.douyinstatic.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/bf8647bffab13c38772c9ff94bf91a9d.jpg',
+      },
+      {
+        preview: false,
+        name: '2D-sticker-temp.psd',
+        status: 'success',
+        uid: 'b7d579069320590ba4b128672eedbae2-1',
+        url:
+          'https://sf6-cdn-tos.douyinstatic.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/bf8647bffab13c38772c9ff94bf91a9d.jpg',
+      },
+      {
+        preview: false,
+        name: '2D-sticker-temp (1).psd',
+        status: 'success',
+        uid: 'b7d579069320590ba4b128672eedbae2-2',
+        url:
+          'https://sf6-cdn-tos.douyinstatic.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/bf8647bffab13c38772c9ff94bf91a9d.jpg',
+      },
+    ];
+  }
+
+  toggle() {
+    this.setState({
+      isOpen: !this.state.isOpen,
+    });
+  }
+
+  render() {
+    const { isOpen } = this.state;
+    return (
+      <div>
+        <Collapsible isOpen={isOpen} collapseHeight={120}>
+          <Upload
+            dragable={true}
+            name="file" // accept={ALLOW_FILE}
+            defaultFileList={[
+              {
                 preview: false,
                 name: '2D (2).ecpj',
                 status: 'success',
                 uid: 'd116a179410eb0ca18e66074509bde93-0',
-                url: 'https://sf6-cdn-tos.douyinstatic.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/bf8647bffab13c38772c9ff94bf91a9d.jpg',
-            },
-            {
+                url:
+                  'https://sf6-cdn-tos.douyinstatic.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/bf8647bffab13c38772c9ff94bf91a9d.jpg',
+              },
+              {
                 preview: false,
                 name: '2D-sticker-temp.psd',
                 status: 'success',
                 uid: 'b7d579069320590ba4b128672eedbae2-1',
-                url: 'https://sf6-cdn-tos.douyinstatic.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/bf8647bffab13c38772c9ff94bf91a9d.jpg',
-            },
-            {
+                url:
+                  'https://sf6-cdn-tos.douyinstatic.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/bf8647bffab13c38772c9ff94bf91a9d.jpg',
+              },
+              {
                 preview: false,
                 name: '2D-sticker-temp (1).psd',
                 status: 'success',
                 uid: 'b7d579069320590ba4b128672eedbae2-2',
-                url: 'https://sf6-cdn-tos.douyinstatic.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/bf8647bffab13c38772c9ff94bf91a9d.jpg',
-            },
-        ];
-    }
-
-    toggle() {
-        this.setState({
-            isOpen: !this.state.isOpen,
-        });
-    }
-
-    render() {
-        const { isOpen } = this.state;
-        return (
-            <div>
-                <Collapsible isOpen={isOpen} collapseHeight={120}>
-                    <Upload
-                        dragable={true}
-                        name="file" // accept={ALLOW_FILE}
-                        defaultFileList={[
-                            {
-                                preview: false,
-                                name: '2D (2).ecpj',
-                                status: 'success',
-                                uid: 'd116a179410eb0ca18e66074509bde93-0',
-                                url:
-                                    'https://sf6-cdn-tos.douyinstatic.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/bf8647bffab13c38772c9ff94bf91a9d.jpg',
-                            },
-                            {
-                                preview: false,
-                                name: '2D-sticker-temp.psd',
-                                status: 'success',
-                                uid: 'b7d579069320590ba4b128672eedbae2-1',
-                                url:
-                                    'https://sf6-cdn-tos.douyinstatic.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/bf8647bffab13c38772c9ff94bf91a9d.jpg',
-                            },
-                            {
-                                preview: false,
-                                name: '2D-sticker-temp (1).psd',
-                                status: 'success',
-                                uid: 'b7d579069320590ba4b128672eedbae2-2',
-                                url:
-                                    'https://sf6-cdn-tos.douyinstatic.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/bf8647bffab13c38772c9ff94bf91a9d.jpg',
-                            },
-                        ]}
-                        dragMainText="点击上传文件或拖拽文件到这里"
-                        dragSubText="图片、PDF、PPT、Word、视频等"
-                        onError={this.uploadError}
-                        onSuccess={(...args) => this.uploadSuccess(i, ...args)}
-                        onRemove={(...args) => this.onRemoveFile(i, ...args)}
-                        onProgress={() =>
-                            this.setState({
-                                fileLoading: true,
-                            })
-                        }
-                    >
-                        <Button icon={<IconUpload />} theme="light">
-                            点击上传
-                        </Button>
-                    </Upload>
-                </Collapsible>
-                <Button onClick={this.toggle}>{isOpen ? '剩余1项' : '展开'}</Button>
-            </div>
-        );
-    }
+                url:
+                  'https://sf6-cdn-tos.douyinstatic.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/bf8647bffab13c38772c9ff94bf91a9d.jpg',
+              },
+            ]}
+            dragMainText="点击上传文件或拖拽文件到这里"
+            dragSubText="图片、PDF、PPT、Word、视频等"
+            onError={this.uploadError}
+            onSuccess={(...args) => this.uploadSuccess(i, ...args)}
+            onRemove={(...args) => this.onRemoveFile(i, ...args)}
+            onProgress={() =>
+              this.setState({
+                fileLoading: true,
+              })
+            }
+          >
+            <Button icon={<IconUpload />} theme="light">
+              点击上传
+            </Button>
+          </Upload>
+        </Collapsible>
+        <Button onClick={this.toggle}>{isOpen ? '剩余1项' : '展开'}</Button>
+      </div>
+    );
+  }
 }
 
-stories.add('collapsible with Upload', () => <WithUpload />);
+export const CollapsibleWithUpload = () => <WithUpload />;
 
 class CusHeight extends React.Component {
-    constructor(props) {
-        super(props);
-        this.state = {
-            isOpen: false,
-        };
-        this.toggle = this.toggle.bind(this);
-    }
-
-    toggle() {
-        this.setState({
-            isOpen: !this.state.isOpen,
-        });
-    }
-
-    render() {
-        const { isOpen } = this.state;
-        const maskStyle = isOpen
-            ? {}
-            : {
-                  WebkitMaskImage:
-                      'linear-gradient(to bottom, black 0%, rgba(0, 0, 0, 1) 60%, rgba(0, 0, 0, 0.2) 80%, transparent 100%)',
-              };
-        const collapsed = (
-            <ul>
-                <li>
-                    <p>Semi Design 以内容优先进行设计。</p>
-                </li>
-                <li>
-                    <p>更容易地自定义主题。</p>
-                </li>
-                <li>
-                    <p>适用国际化场景。</p>
-                </li>
-                <li>
-                    <p>效率场景加入人性化关怀。</p>
-                </li>
-            </ul>
-        );
-        const linkStyle = {
-            position: 'absolute',
-            left: 0,
-            right: 0,
-            textAlign: 'center',
-            bottom: -10,
-            fontWeight: 700,
-            cursor: 'pointer',
+  constructor(props) {
+    super(props);
+    this.state = {
+      isOpen: false,
+    };
+    this.toggle = this.toggle.bind(this);
+  }
+
+  toggle() {
+    this.setState({
+      isOpen: !this.state.isOpen,
+    });
+  }
+
+  render() {
+    const { isOpen } = this.state;
+    const maskStyle = isOpen
+      ? {}
+      : {
+          WebkitMaskImage:
+            'linear-gradient(to bottom, black 0%, rgba(0, 0, 0, 1) 60%, rgba(0, 0, 0, 0.2) 80%, transparent 100%)',
         };
-        console.log('out state', isOpen);
-        return (
-            <>
-                <Button onClick={this.toggle}>Toggle</Button>
-                <div
-                    style={{
-                        position: 'relative',
-                    }}
-                >
-                    <Collapsible
-                        isOpen={isOpen}
-                        collapseHeight={40}
-                        style={{ ...maskStyle }}
-                        onInnerStateOpen={bool => {
-                            if (isOpen !== bool) {
-                                this.setState({
-                                    isOpen: bool,
-                                });
-                            }
-                        }}
-                    >
-                        {collapsed}
-                    </Collapsible>
-                    {isOpen ? null : (
-                        <a onClick={this.toggle} style={{ ...linkStyle }}>
-                            + Show More
-                        </a>
-                    )}
-                </div>
-            </>
-        );
-    }
+    const collapsed = (
+      <ul>
+        <li>
+          <p>Semi Design 以内容优先进行设计。</p>
+        </li>
+        <li>
+          <p>更容易地自定义主题。</p>
+        </li>
+        <li>
+          <p>适用国际化场景。</p>
+        </li>
+        <li>
+          <p>效率场景加入人性化关怀。</p>
+        </li>
+      </ul>
+    );
+    const linkStyle = {
+      position: 'absolute',
+      left: 0,
+      right: 0,
+      textAlign: 'center',
+      bottom: -10,
+      fontWeight: 700,
+      cursor: 'pointer',
+    };
+    console.log('out state', isOpen);
+    return (
+      <>
+        <Button onClick={this.toggle}>Toggle</Button>
+        <div
+          style={{
+            position: 'relative',
+          }}
+        >
+          <Collapsible
+            isOpen={isOpen}
+            collapseHeight={40}
+            style={{ ...maskStyle }}
+            onInnerStateOpen={bool => {
+              if (isOpen !== bool) {
+                this.setState({
+                  isOpen: bool,
+                });
+              }
+            }}
+          >
+            {collapsed}
+          </Collapsible>
+          {isOpen ? null : (
+            <a onClick={this.toggle} style={{ ...linkStyle }}>
+              + Show More
+            </a>
+          )}
+        </div>
+      </>
+    );
+  }
 }
 
-stories.add('collapse height', () => <CusHeight />);
+export const CollapseHeight = () => <CusHeight />;
 
 const Child = ({ onClick }) => {
-    const [isCOpen, setIsCOpen] = useState(false);
-    return (
-        <div>
-            <div
-                style={{
-                    display: isCOpen ? 'block' : 'none',
-                    height: 200,
-                    background: 'green',
-                }}
-            >
-                child
-            </div>
-            <Button
-                onClick={() => {
-                    setIsCOpen(!isCOpen);
-                    onClick();
-                }}
-            >
-                Toggle
-            </Button>
-        </div>
-    );
+  const [isCOpen, setIsCOpen] = useState(false);
+  return (
+    <div>
+      <div
+        style={{
+          display: isCOpen ? 'block' : 'none',
+          height: 200,
+          background: 'green',
+        }}
+      >
+        child
+      </div>
+      <Button
+        onClick={() => {
+          setIsCOpen(!isCOpen);
+          onClick();
+        }}
+      >
+        Toggle
+      </Button>
+    </div>
+  );
 }; // dynamic update content, children comp need to separate from parent to avoid rerender of entire comp
 
 const DynamDemo = () => {
-    const [isOpen, setIsOpen] = useState(true);
-    const [reCalcKey, setReCalcKey] = useState(0);
-    return (
+  const [isOpen, setIsOpen] = useState(true);
+  const [reCalcKey, setReCalcKey] = useState(0);
+  return (
+    <div>
+      <Button onClick={() => setIsOpen(!isOpen)}>折叠</Button>
+      <Collapsible isOpen={isOpen}>
         <div>
-            <Button onClick={() => setIsOpen(!isOpen)}>折叠</Button>
-            <Collapsible isOpen={isOpen}>
-                <div>
-                    <div
-                        style={{
-                            height: 200,
-                            background: 'blue',
-                        }}
-                    >
-                        father
-                    </div>
-                    <Child onClick={() => setReCalcKey(reCalcKey + 1)} />
-                </div>
-            </Collapsible>
+          <div
+            style={{
+              height: 200,
+              background: 'blue',
+            }}
+          >
+            father
+          </div>
+          <Child onClick={() => setReCalcKey(reCalcKey + 1)} />
         </div>
-    );
+      </Collapsible>
+    </div>
+  );
 };
 
-stories.add('dynamic collapsible', () => <DynamDemo />);
+export const DynamicCollapsible = () => <DynamDemo />;

+ 23 - 9
packages/semi-ui/configProvider/_story/configProvider.stories.js

@@ -1,16 +1,30 @@
 import React from 'react';
-import { storiesOf } from '@storybook/react';
 import ChangeTimeZone from './ChangeTimeZone';
 import GetContainer from './GetPopupContainer';
-import RTLWrapper from './RTLDirection/RTLWrapper'
-import RTLTable  from './RTLDirection/RTLTable';
-import RTLForm  from './RTLDirection/RTLForm';
+import RTLWrapper from './RTLDirection/RTLWrapper';
+import RTLTable from './RTLDirection/RTLTable';
+import RTLForm from './RTLDirection/RTLForm';
 
-const stories = storiesOf('ConfigProvider', module);
-stories.add(`change timeZone`, () => <ChangeTimeZone />);
+export default {
+  title: 'ConfigProvider',
+  parameters: {
+    chromatic: { disableSnapshot: true },
+  },
+}
 
-stories.add(`getPopupContainer`, () => <GetContainer />);
+export {
+  ChangeTimeZone,
+  GetContainer,
+}
 
-stories.add(`RTL Table`, () => <RTLWrapper><RTLTable /></RTLWrapper>);
+export const RTLTableDemo = () => (
+  <RTLWrapper>
+    <RTLTable />
+  </RTLWrapper>
+);
 
-stories.add(`RTL Form`, () => <RTLWrapper><RTLForm /></RTLWrapper>);
+export const RTLFormDemo = () => (
+  <RTLWrapper>
+    <RTLForm />
+  </RTLWrapper>
+);

+ 4 - 0
packages/semi-ui/datePicker/_story/BetterRangePicker/index.jsx

@@ -25,6 +25,10 @@ const presets = [
 const baseDate = new Date(baseYear, baseMon, baseDay, 8, 8, 8, 8);
 const currentValue = [new Date(baseDate), new Date(baseDate).setDate(baseDay + dayOffset)];
 
+Demo.parameters = {
+    chromatic: { disableSnapshot: false },
+};
+
 export default function Demo(props = {}) {
     const style = { width: 240 };
     return (

+ 4 - 0
packages/semi-ui/datePicker/_story/CustomTrigger/index.jsx

@@ -4,6 +4,10 @@ import { IconClose, IconChevronDown } from '@douyinfe/semi-icons';
 
 import { DatePicker, Button } from '../../../index';
 
+Demo.parameters = {
+    chromatic: { disableSnapshot: true },
+};
+
 export default function Demo() {
     const [date, setDate] = useState(new Date());
     const formatToken = 'yyyy-MM-dd';

+ 83 - 0
packages/semi-ui/datePicker/_story/DatePickerSlot/index.jsx

@@ -0,0 +1,83 @@
+/* eslint-disable max-len */
+import React, { useState, useMemo } from 'react';
+import { DatePicker, Icon, Typography, Space, Tabs, TabPane } from '../../../index';
+import './index.scss';
+
+const { Text } = Typography;
+
+export default function Demo() {
+    const [activeTab, setActiveTab] = useState('1');
+    const [date, setDate] = useState();
+    const uedDisabledDate = currentDate => currentDate && currentDate.getDate() > 10 && currentDate.getDate() < 15;
+    const testDisabledDate = currentDate => currentDate && currentDate.getDate() > 15 && currentDate.getDate() < 25;
+
+    const handleTabChange = tab => {
+        setActiveTab(tab);
+        setDate();
+    };
+
+    const handleDateChange = value => {
+        setDate(value);
+    };
+
+    const disabledDate = useMemo(() => (activeTab === '1' ? uedDisabledDate : testDisabledDate), [activeTab]);
+
+    const TopSlot = function (props) {
+        const { style } = props;
+        return (
+            <Tabs size="small" onChange={handleTabChange} activeKey={activeTab} style={{ padding: '12px 20px 0', ...style }}>
+                <TabPane tab="UED 排期" itemKey="1" />
+                <TabPane tab="测试排期" itemKey="2" />
+            </Tabs>
+        );
+    };
+
+    const BottomSlot = function (props) {
+        const { style } = props;
+        return (
+            <Space style={{ padding: '12px 20px', ...style }}>
+                <Icon type="bulb" style={{ color: 'rgba(var(--amber-5), 1)' }} />
+                <Text strong style={{ color: 'var(--color-text-2)' }}>
+                    定版前请阅读
+                </Text>
+                <Text link={{ href: 'https://semi.design/', target: '_blank' }}>发版须知</Text>
+            </Space>
+        );
+    };
+
+    const MonthBottomSlot = function (props) {
+        const { style } = props;
+        return (
+            <Space style={{ padding: '12px 20px', ...style }}>
+                <Icon type="bulb" style={{ color: 'rgba(var(--amber-5), 1)' }} />
+                <Text strong style={{ color: 'var(--color-text-2)' }}>
+                    请阅读
+                </Text>
+                <Text link={{ href: 'https://semi.design/', target: '_blank' }}>须知</Text>
+            </Space>
+        );
+    };
+
+    return (
+        <div>
+            <span>topSlot</span>
+            <DatePicker topSlot={<TopSlot />} disabledDate={disabledDate} value={date} onChange={handleDateChange} />
+            <br />
+            <br />
+            <span>bottomSlot</span>
+            <DatePicker bottomSlot={<BottomSlot />} />
+            <br />
+            <br />
+            <span>bottomSlot+dateTimeRange</span>
+            <DatePicker type="dateTimeRange" bottomSlot={<BottomSlot />} style={{ width: 300 }} />
+            <br />
+            <br />
+            <span>topSlot+month</span>
+            <DatePicker type="month" bottomSlot={<MonthBottomSlot />} />
+            <br />
+            <br />
+            <span>topSlot+bottomSlot+compact</span>
+            <DatePicker topSlot={<TopSlot style={{ padding: '8px 12px 0' }} />} bottomSlot={<BottomSlot style={{ padding: '8px 12px' }} />} density="compact" />
+        </div>
+    );
+}

+ 223 - 164
packages/semi-ui/datePicker/_story/datePicker.stories.js

@@ -1,7 +1,15 @@
 import React, { useState, useRef } from 'react';
-import { storiesOf } from '@storybook/react';
-import withPropsCombinations from 'react-storybook-addon-props-combinations';
-import { addDays, addWeeks, addMonths, isBefore, startOfMonth, endOfMonth, parseISO, startOfWeek, endOfWeek } from 'date-fns';
+import {
+  addDays,
+  addWeeks,
+  addMonths,
+  isBefore,
+  startOfMonth,
+  endOfMonth,
+  parseISO,
+  startOfWeek,
+  endOfWeek,
+} from 'date-fns';
 import { Space, ConfigProvider, InputGroup, InputNumber, Form, withField } from '../../index';
 
 // stores
@@ -29,16 +37,43 @@ import DatePickerTimeZone from './DatePickerTimeZone';
 import BetterRangePicker from './BetterRangePicker';
 import SyncSwitchMonth from './SyncSwitchMonth';
 
-const stories = storiesOf('DatePicker', module);
+export default {
+  title: 'DatePicker',
+  parameters: {
+    chromatic: { disableSnapshot: true },
+  },
+}
 
-// stories.addDecorator(withKnobs);;
+export {
+  ControlledDemo,
+  NeedConfirmDemo,
+  ExceptionDemo,
+  AllTypesDemo,
+  Callbacks,
+  DisabledDate,
+  CustomTrigger,
+  OverPopover,
+  OnChangeWithDateFirst,
+  RenderDate,
+  RenderFullDate,
+  Autofocus,
+  DateOffset,
+  CycledDatePicker,
+  AutoSwitchDate,
+  TimepikcerOpts,
+  Density,
+  DatePickerSlot,
+  DatePickerTimeZone,
+  BetterRangePicker,
+  SyncSwitchMonth
+}
 
 const demoDiv = {
   marginTop: '20px',
   marginLeft: '20px',
 };
 
-stories.add('DatePicker default', () => (
+export const DatePickerDefault = () => (
   <div style={demoDiv}>
     <span>datePicker施工现场</span>
     <DatePicker
@@ -54,7 +89,10 @@ stories.add('DatePicker default', () => (
     <br />
 
     <span>defaultValue: new Date('2019-07-07')</span>
-    <DatePicker defaultValue={new Date('2019-07-07')} onOpenChange={isOpen => console.log(isOpen)} />
+    <DatePicker
+      defaultValue={new Date('2019-07-07')}
+      onOpenChange={isOpen => console.log(isOpen)}
+    />
     <br />
 
     <span>defaultValue: 2019-07-09</span>
@@ -62,11 +100,14 @@ stories.add('DatePicker default', () => (
     <br />
 
     <span>defaultValue: 1569888000000</span>
-    <DatePicker defaultValue={1569888000000} onChange={(input, value) => console.log({ input, value })} />
+    <DatePicker
+      defaultValue={1569888000000}
+      onChange={(input, value) => console.log({ input, value })}
+    />
   </div>
-));
+);
 
-stories.add('DatePicker callbacks', () => {
+export const DatePickerCallbacks = () => {
   const printArgs = (...args) => console.log(...args);
 
   return (
@@ -84,14 +125,17 @@ stories.add('DatePicker callbacks', () => {
       <br />
 
       <span>defaultValue: 1569888000000</span>
-      <DatePicker defaultValue={1569888000000} onChange={(input, value) => console.log(input, value)} />
+      <DatePicker
+        defaultValue={1569888000000}
+        onChange={(input, value) => console.log(input, value)}
+      />
     </div>
   );
-});
+};
 
-stories.add('DatePicker multiple', () => <Multiple />);
+export const DatePickerMultiple = () => <Multiple />;
 
-stories.add('DateRangePicker', () => (
+export const DateRangePicker = () => (
   <div style={demoDiv}>
     <div>dateRangePicker</div>
     <DatePicker type="dateRange" insetLabel="结束日期" prefix="test" validateStatus="error" />
@@ -106,18 +150,24 @@ stories.add('DateRangePicker', () => (
     <br />
 
     <div>compact dateRangePicker</div>
-    <DatePicker type="dateRange" density='compact' validateStatus="warning" />
+    <DatePicker type="dateRange" density="compact" validateStatus="warning" />
     <br />
 
     <div>dateRangePicker with offset</div>
-    <DatePicker type="dateRange" startDateOffset={date => startOfWeek(date, { weekStartsOn: 1 })}
-                endDateOffset={date => endOfWeek(date, { weekStartsOn: 1 })} />
+    <DatePicker
+      type="dateRange"
+      startDateOffset={date => startOfWeek(date, { weekStartsOn: 1 })}
+      endDateOffset={date => endOfWeek(date, { weekStartsOn: 1 })}
+    />
     <br />
 
     <div>defaultValue:07/01-08/02</div>
     <DatePicker type="dateRange" defaultValue={[new Date('2019-07-01'), new Date('2019-08-02')]} />
   </div>
-));
+);
+DateRangePicker.parameters = {
+  chromatic: { disableSnapshot: false },
+};
 
 const presets = [
   {
@@ -162,14 +212,19 @@ const presets = [
   },
 ];
 
-stories.add('DatePicker with presets', () => {
+export const DatePickerWithPresets = () => {
   const onPresetClick = (item, e) => {
     console.log('preset click', item, e);
-  }
-  return (    
+  };
+  return (
     <div style={demoDiv}>
       <span>带快捷选择的DatePicker</span>
-      <DatePicker type="dateRange" presets={presets} onPresetClick={onPresetClick} onChange={(...args) => console.log(...args)} />
+      <DatePicker
+        type="dateRange"
+        presets={presets}
+        onPresetClick={onPresetClick}
+        onChange={(...args) => console.log(...args)}
+      />
       <DatePicker
         type="dateTime"
         presets={presets.map(preset => ({
@@ -200,20 +255,20 @@ stories.add('DatePicker with presets', () => {
       />
     </div>
   );
-});
+};
 
 function isDisabled(dayStr) {
   return isBefore(new Date(dayStr), new Date());
 }
 
-stories.add('DatePicker disabledDate', () => (
+export const DatePickerDisabledDate = () => (
   <div style={demoDiv}>
     <span>不可选日期</span>
     <DatePicker type="dateRange" presets={presets} disabledDate={isDisabled} />
   </div>
-));
+);
 
-stories.add('DateTimePicker', () => (
+export const DateTimePicker = () => (
   <div style={demoDiv}>
     <span>dateTimePicker</span>
     <DatePicker
@@ -222,9 +277,9 @@ stories.add('DateTimePicker', () => (
       onChange={(...args) => console.log('onChange: ', ...args)}
     />
   </div>
-));
+);
 
-stories.add('DateTimeRange Picker', () => (
+export const DateTimeRangePicker = () => (
   <div style={demoDiv}>
     <span>dateTimeRangePicker</span>
     <DatePicker type="dateTimeRange" defaultPickerValue={parseISO('2020-02-20 20:00:00')} />
@@ -238,9 +293,9 @@ stories.add('DateTimeRange Picker', () => (
     <DatePicker type="dateTimeRange" multiple />
     <br />
   </div>
-));
+);
 
-stories.add('Year Picker', () => (
+export const YearPicker = () => (
   <>
     <div>
       <span>Year Picker</span>
@@ -251,9 +306,9 @@ stories.add('Year Picker', () => (
       <DatePicker type="dateTimeRange" presets={presets} />
     </div>
   </>
-));
+);
 
-stories.add('Month Picker', () => {
+export const MonthPicker = () => {
   const Demo = () => {
     const [controlledValue, setControlledValue] = useState('2019-09');
 
@@ -297,61 +352,31 @@ stories.add('Month Picker', () => {
   };
 
   return <Demo />;
-});
+};
 
-stories.add('propTypes and defaultProps', () => (
+export const PropTypesAndDefaultProps = () => (
   <div>
     <article>
       <p>{JSON.stringify(Object.keys(DatePicker.propTypes))}</p>
       <p>{JSON.stringify(DatePicker.defaultProps)}</p>
     </article>
   </div>
-));
-
-stories.add('受控组件', () => <ControlledDemo />);
-
-stories.add('inputReadOnly', () => <DatePicker inputReadOnly={true} />);
-
-stories.add('need confirm', () => <NeedConfirmDemo />);
-
-stories.add('边界问题', () => <ExceptionDemo />);
+);
 
-stories.add('all types', () => <AllTypesDemo />);
-stories.add('callbacks', () => <Callbacks />);
+export const InputReadOnly = () => <DatePicker inputReadOnly={true} />;
 
-stories.add('Disabled Date', () => <DisabledDate />);
-
-stories.add('custom trigger', () => <CustomTrigger />);
-stories.add('over popover', () => <OverPopover />);
-
-stories.add('onChange with Date first', () => <OnChangeWithDateFirst />);
-
-stories.add('renderDate', () => <RenderDate />);
-stories.add('renderFullDate', () => <RenderFullDate />);
-stories.add('autoFocus', () => <Autofocus />);
-stories.add('startDateOffset & endDateOffset', () => <DateOffset />);
-stories.add('cycled', () => <CycledDatePicker />);
-stories.add('autoSwitchDate', () => <AutoSwitchDate />);
-
-stories.add('dropdownClassName & dropdownStyle', () => (
+export const DropdownClassNameDropdownStyle = () => (
   <div>
     <h4>fontSize: 16,dropdownClassName: 'my-datePicker'</h4>
-    <DatePicker 
+    <DatePicker
       dropdownStyle={{ fontSize: 16 }}
-      dropdownClassName='my-datePicker'
+      dropdownClassName="my-datePicker"
       onChange={(date, dateString) => console.log(dateString)}
     />
   </div>
-));
-stories.add('timepickerOpts', () => <TimepikcerOpts />);
+);
 
-stories.add('density', () => <Density />);
-
-stories.add('topSlot/bottomSlot', () => <DatePickerSlot />);
-
-stories.add('timeZone', () => <DatePickerTimeZone />);
-
-stories.add('custom placeholder', () => (
+export const CustomPlaceholder = () => (
   <Space wrap>
     <DatePicker placeholder="请选择日期" insetLabel="默认" />
     <DatePicker placeholder={undefined} insetLabel="undefined" />
@@ -360,48 +385,51 @@ stories.add('custom placeholder', () => (
     <DatePicker placeholder={null} insetLabel="null" />
     <DatePicker placeholder="" type="dateRange" insetLabel="空字符串" />
   </Space>
-));
-
-stories.add('better range picker', () => <BetterRangePicker />);
-
-stories.add('syncSwitchMonth', () => <SyncSwitchMonth />);
+);
+CustomPlaceholder.parameters = {
+  chromatic: { disableSnapshot: false },
+};
 
-stories.add('fix notifyChange', () => {
+export const FixNotifyChange = () => {
   function Demo() {
-    const [tz,setTz] = useState(0);
+    const [tz, setTz] = useState(0);
     const [value, setVal] = useState();
     const [value2, setVal2] = useState();
     const [value3, setVal3] = useState();
     const [value4, setVal4] = useState();
-    const withLog = (fn) => {
-      return (val => {
-          console.log('notifyChange', val);
-          fn(val);
-      });
-    }
+    const withLog = fn => {
+      return val => {
+        console.log('notifyChange', val);
+        fn(val);
+      };
+    };
     return (
-        <ConfigProvider timeZone={tz}>
-            <InputGroup>
-                <InputNumber defaultValue={0} onChange={setTz} hideButtons />
-                <DatePicker type='dateTimeRange' value={value} onChange={withLog(setVal)}  />
-                <DatePicker type='dateTimeRange' needConfirm value={value2} onConfirm={withLog(setVal2)}  />
-                <DatePicker type='date' value={value3} onChange={withLog(setVal3)}  />
-                <DatePicker type='dateRange' value={value4} onChange={withLog(setVal4)}  />
-            </InputGroup>
-        </ConfigProvider> 
+      <ConfigProvider timeZone={tz}>
+        <InputGroup>
+          <InputNumber defaultValue={0} onChange={setTz} hideButtons />
+          <DatePicker type="dateTimeRange" value={value} onChange={withLog(setVal)} />
+          <DatePicker
+            type="dateTimeRange"
+            needConfirm
+            value={value2}
+            onConfirm={withLog(setVal2)}
+          />
+          <DatePicker type="date" value={value3} onChange={withLog(setVal3)} />
+          <DatePicker type="dateRange" value={value4} onChange={withLog(setVal4)} />
+        </InputGroup>
+      </ConfigProvider>
     );
-  };
+  }
   return <Demo />;
+};
 
-});
-
-stories.add('select not disabled date(v1.26+)', () => {
+export const SelectNotDisabledDateV126 = () => {
   const defaultValue = ['2021-08-06', '2021-08-15'];
   const disabledMonth = dateStr => {
     const date = new Date(dateStr);
     const month = date.getMonth();
     if (month === 7) {
-        return true;
+      return true;
     }
     return false;
   };
@@ -409,7 +437,7 @@ stories.add('select not disabled date(v1.26+)', () => {
     const date = new Date(dateStr);
     const day = date.getDate();
     if (day > 20 && day < 25) {
-        return true;
+      return true;
     }
     return false;
   };
@@ -419,7 +447,7 @@ stories.add('select not disabled date(v1.26+)', () => {
     motion: false,
     defaultValue,
     onChange: (...args) => console.log('changed', ...args),
-    style: { width: 300 }
+    style: { width: 300 },
   };
 
   return (
@@ -429,19 +457,21 @@ stories.add('select not disabled date(v1.26+)', () => {
       <h4>date type + multiple select + given disabled defaultValue</h4>
       <DatePicker {...props} type="date" multiple disabledDate={disabledDate} />
     </>
-  )
-});
+  );
+};
 
-const CustomDatePicker = (props) => {
+SelectNotDisabledDateV126.story = {
+  name: 'select not disabled date(v1.26+)',
+};
+
+const CustomDatePicker = props => {
   const { fieldRef, ...rest } = props;
-  return (
-    <DatePicker {...rest} ref={fieldRef}  />
-  );
+  return <DatePicker {...rest} ref={fieldRef} />;
 };
 
 const CustomFieldDatePicker = withField(CustomDatePicker);
 
-stories.add('fix onFocus', () => {
+export const FixOnFocus = () => {
   function FocusDemo() {
     const [open1, setOpen1] = useState(false);
     const [open2, setOpen2] = useState(false);
@@ -449,16 +479,16 @@ stories.add('fix onFocus', () => {
     const ref = useRef();
     const ref2 = useRef();
     const presets = [
-        {
-            text: 'Today',
-            start: new Date(),
-            end: new Date(),
-        },
-        {
-            text: 'Tomorrow',
-            start: new Date(new Date().valueOf() + 1000 * 3600 * 24),
-            end: new Date(new Date().valueOf() + 1000 * 3600 * 24),
-        },
+      {
+        text: 'Today',
+        start: new Date(),
+        end: new Date(),
+      },
+      {
+        text: 'Tomorrow',
+        start: new Date(new Date().valueOf() + 1000 * 3600 * 24),
+        end: new Date(new Date().valueOf() + 1000 * 3600 * 24),
+      },
     ];
     return (
       <>
@@ -467,16 +497,19 @@ stories.add('fix onFocus', () => {
           presets={presets}
           open={open1}
           onPresetClick={() => {
-              setOpen1(false);
+            setOpen1(false);
           }}
           onFocus={() => {
-              console.log('focus');
-              setOpen1(true);
+            console.log('focus');
+            setOpen1(true);
+          }}
+          onBlur={() => {
+            console.log('blur');
           }}
-          onBlur={() => {console.log('blur')}}
           style={{ width: 300 }}
         />
-        <br /><br />
+        <br />
+        <br />
         <DatePicker
           type="dateTimeRange"
           presets={presets}
@@ -493,40 +526,48 @@ stories.add('fix onFocus', () => {
             console.log('focus');
             setOpen2(true);
           }}
-          onBlur={() => {console.log('blur')}}
+          onBlur={() => {
+            console.log('blur');
+          }}
           style={{ width: 500 }}
           ref={ref}
         />
         <Form>
           <CustomFieldDatePicker
-              type="dateTimeRange"
-              field="a"
-              label="Form.DatePicker"
-              presets={presets}
-              open={open3}
-              onPresetClick={() => {
-                console.log('click presets', ref2);
-                setOpen3(false);
-                setTimeout(() => {
-                  ref2.current &&  ref2.current.foundation.closePanel();
-                }, 0);
-              }}
-              onFocus={() => {
-                console.log('focus');
-                setOpen3(true);
-              }}
-              onBlur={() => {console.log('blur')}}
-              style={{ width: 500 }}
-              fieldRef={ref2}
+            type="dateTimeRange"
+            field="a"
+            label="Form.DatePicker"
+            presets={presets}
+            open={open3}
+            onPresetClick={() => {
+              console.log('click presets', ref2);
+              setOpen3(false);
+              setTimeout(() => {
+                ref2.current && ref2.current.foundation.closePanel();
+              }, 0);
+            }}
+            onFocus={() => {
+              console.log('focus');
+              setOpen3(true);
+            }}
+            onBlur={() => {
+              console.log('blur');
+            }}
+            style={{ width: 500 }}
+            fieldRef={ref2}
           />
         </Form>
       </>
     );
-  };
-  return <FocusDemo />
-});
+  }
+  return <FocusDemo />;
+};
+
+FixOnFocus.story = {
+  name: 'fix onFocus',
+};
 
-stories.add('fix disabledTime callback #1418', () => {
+export const FixDisabledTimeCallback1418 = () => {
   function Demo() {
     const disabledTime2 = (date, panelType) => {
       console.log('disabledTime callback parameter: ', date, panelType);
@@ -541,37 +582,55 @@ stories.add('fix disabledTime callback #1418', () => {
       <>
         <strong>fix disabledTime callback parameter bug</strong>
         <DatePicker
-            type="dateTimeRange"
-            hideDisabledOptions={false}
-            disabledTime={disabledTime2}
-            defaultValue={['2021-09-08', '2021-10-03']}
-            style={{ width: 400 }}
+          type="dateTimeRange"
+          hideDisabledOptions={false}
+          disabledTime={disabledTime2}
+          defaultValue={['2021-09-08', '2021-10-03']}
+          style={{ width: 400 }}
         />
         <DatePicker
-            type="dateTime"
-            hideDisabledOptions={false}
-            defaultValue={'2021-09-08'}
-            disabledTime={disabledTime2}
-            style={{ width: 400 }}
+          type="dateTime"
+          hideDisabledOptions={false}
+          defaultValue={'2021-09-08'}
+          disabledTime={disabledTime2}
+          style={{ width: 400 }}
         />
       </>
     );
-  };
+  }
 
   return <Demo />;
-});
+};
 
-stories.add('rangeSeparator', () => (
+FixDisabledTimeCallback1418.story = {
+  name: 'fix disabledTime callback #1418',
+};
+
+export const RangeSeparator = () => (
   <Space wrap>
     <div>
       <div>custom rangeSeparator</div>
-      <DatePicker type="dateRange" rangeSeparator="-" defaultValue={[new Date('2019-07-01'), new Date('2019-08-02')]} />
-      <DatePicker type="dateTimeRange" rangeSeparator="-" defaultValue={[new Date('2019-07-01'), new Date('2019-08-02')]} />
+      <DatePicker
+        type="dateRange"
+        rangeSeparator="-"
+        defaultValue={[new Date('2019-07-01'), new Date('2019-08-02')]}
+      />
+      <DatePicker
+        type="dateTimeRange"
+        rangeSeparator="-"
+        defaultValue={[new Date('2019-07-01'), new Date('2019-08-02')]}
+      />
     </div>
     <div>
       <div>default rangeSeparator</div>
-      <DatePicker type="dateRange" defaultValue={[new Date('2019-07-01'), new Date('2019-08-02')]} />
-      <DatePicker type="dateTimeRange" defaultValue={[new Date('2019-07-01'), new Date('2019-08-02')]} />
+      <DatePicker
+        type="dateRange"
+        defaultValue={[new Date('2019-07-01'), new Date('2019-08-02')]}
+      />
+      <DatePicker
+        type="dateTimeRange"
+        defaultValue={[new Date('2019-07-01'), new Date('2019-08-02')]}
+      />
     </div>
   </Space>
-));
+);

+ 46 - 45
packages/semi-ui/descriptions/_story/descriptions.stories.js

@@ -1,10 +1,11 @@
 import React from 'react';
-import { storiesOf } from '@storybook/react';
 // import { withKnobs, text, boolean } from '@storybook/addon-knobs';
 
 import Descriptions from '../index';
 
-const stories = storiesOf('Descriptions', module);
+export default {
+  title: 'Descriptions',
+}
 
 let data = [
     // ShortId: '火山号',
@@ -46,49 +47,49 @@ let data4 = [
     { key: '7天留存', value: '103.4M' },
 ];
 
-stories.add('Descriptions default', () => (
-    <div>
-        <Descriptions data={data} />
-        <Descriptions align='justify' data={data2} />
-        <Descriptions align='left' data={data3} />
-        <Descriptions align='plain' data={data2} />
-    </div>
-));
+export const DescriptionsDefault = () => (
+  <div>
+    <Descriptions data={data} />
+    <Descriptions align="justify" data={data2} />
+    <Descriptions align="left" data={data3} />
+    <Descriptions align="plain" data={data2} />
+  </div>
+);
 
-stories.add('Descriptions double row', () => (
-    <div>
-        <Descriptions data={data4} row size='small' />
-        <Descriptions data={data4} row />
-        <Descriptions data={data4} row size='large' />
-    </div>
-));
+export const DescriptionsDoubleRow = () => (
+  <div>
+    <Descriptions data={data4} row size="small" />
+    <Descriptions data={data4} row />
+    <Descriptions data={data4} row size="large" />
+  </div>
+);
 
-stories.add('Descriptions.Item', () => (
-    <div>
-        <Descriptions>
-            <Descriptions.Item itemKey='实际用户数量'>1,480,000</Descriptions.Item>
-            <Descriptions.Item itemKey='7天留存'>98%</Descriptions.Item>
-            <Descriptions.Item itemKey='安全等级'>3级</Descriptions.Item>
-            <Descriptions.Item itemKey='垂类标签'>电商</Descriptions.Item>
-            <Descriptions.Item itemKey='认证状态'>未认证</Descriptions.Item>
-        </Descriptions>
-        <br />
-        <Descriptions row size='small'>
-            <Descriptions.Item itemKey='实际用户数量'>1,480,000</Descriptions.Item>
-            <Descriptions.Item itemKey='7天留存'>98%</Descriptions.Item>
-            <Descriptions.Item itemKey='安全等级'>3级</Descriptions.Item>
-            <Descriptions.Item itemKey='垂类标签'>电商</Descriptions.Item>
-            <Descriptions.Item itemKey='认证状态'>未认证</Descriptions.Item>
-        </Descriptions>
-        <br />
-        <Descriptions align='justify'>
-            <Descriptions.Item >1,480,000</Descriptions.Item>
-            <Descriptions.Item itemKey='7天留存'>98%</Descriptions.Item>
-            <Descriptions.Item itemKey='安全等级'>3级</Descriptions.Item>
-            <Descriptions.Item itemKey='垂类标签'>电商</Descriptions.Item>
-            <Descriptions.Item itemKey='认证状态'>未认证</Descriptions.Item>
-        </Descriptions>
-        <br />
-    </div>
-));
+export const DescriptionsItem = () => (
+  <div>
+    <Descriptions>
+      <Descriptions.Item itemKey="实际用户数量">1,480,000</Descriptions.Item>
+      <Descriptions.Item itemKey="7天留存">98%</Descriptions.Item>
+      <Descriptions.Item itemKey="安全等级">3级</Descriptions.Item>
+      <Descriptions.Item itemKey="垂类标签">电商</Descriptions.Item>
+      <Descriptions.Item itemKey="认证状态">未认证</Descriptions.Item>
+    </Descriptions>
+    <br />
+    <Descriptions row size="small">
+      <Descriptions.Item itemKey="实际用户数量">1,480,000</Descriptions.Item>
+      <Descriptions.Item itemKey="7天留存">98%</Descriptions.Item>
+      <Descriptions.Item itemKey="安全等级">3级</Descriptions.Item>
+      <Descriptions.Item itemKey="垂类标签">电商</Descriptions.Item>
+      <Descriptions.Item itemKey="认证状态">未认证</Descriptions.Item>
+    </Descriptions>
+    <br />
+    <Descriptions align="justify">
+      <Descriptions.Item>1,480,000</Descriptions.Item>
+      <Descriptions.Item itemKey="7天留存">98%</Descriptions.Item>
+      <Descriptions.Item itemKey="安全等级">3级</Descriptions.Item>
+      <Descriptions.Item itemKey="垂类标签">电商</Descriptions.Item>
+      <Descriptions.Item itemKey="认证状态">未认证</Descriptions.Item>
+    </Descriptions>
+    <br />
+  </div>
+);
 

+ 300 - 304
packages/semi-ui/dropdown/_story/dropdown.stories.js

@@ -1,7 +1,4 @@
 import React from 'react';
-import { storiesOf } from '@storybook/react'; // import { withKnobs, text, boolean } from '@storybook/addon-knobs';
-
-import withPropsCombinations from 'react-storybook-addon-props-combinations';
 import Dropdown from '../index';
 import Avatar from '../../avatar';
 import Button from '@douyinfe/semi-ui/button/index';
@@ -11,325 +8,324 @@ import MultiDropdown from './MultiDropdown';
 import DisabledItem from './DisabledItem';
 import InHoverElements from './InHoverElements';
 import WrapAvatar from './WrapAvatar';
-import { IconChevronDown, IconBox, IconSimiarlity } from '@douyinfe/semi-icons';
+import { IconChevronDown, IconBox, IconSimilarity } from '@douyinfe/semi-icons';
+
+export default {
+  title: 'Dropdown',
+  parameters: {
+    chromatic: { disableSnapshot: true },
+  }
+}
 
-const stories = storiesOf('Dropdown', module); // stories.addDecorator(withKnobs);;
+export {
+  InTableDemo,
+  MultiDropdown,
+  DisabledItem,
+  InHoverElements,
+  WrapAvatar
+}
 
 let style = {
-    display: 'inline-block',
-    padding: '20px',
+  display: 'inline-block',
+  padding: '20px',
 };
 
 const change = visible => {
-    debugger;
+  debugger;
 };
 
-stories.add('Dropdown 1', () => (
-    <div>
-        <div style={style}>
-            <Dropdown
-                trigger="click"
-                render={
-                    <Dropdown.Menu>
-                        <Dropdown.Item disabled>1111</Dropdown.Item>
-                        <Dropdown.Divider />
-                        <Dropdown.Item selected={true}>
-                            2222 What if the text is super long? Longer than whatever you've known
-                        </Dropdown.Item>
-                        <Dropdown.Item>It looks OK</Dropdown.Item>
-                    </Dropdown.Menu>
-                }
-            >
-                <div>分割线</div>
-            </Dropdown>
-        </div>
-
-        <div style={style}>
-            <Dropdown
-                onVisibleChange={change}
-                render={
-                    <Dropdown.Menu>
-                        <Dropdown.Item>333</Dropdown.Item>
-                        <Dropdown.Item>44444</Dropdown.Item>
-                    </Dropdown.Menu>
-                }
-            >
-                hover
-            </Dropdown>
-        </div>
-
-        <br />
+export const Dropdown1 = () => (
+  <div>
+    <div style={style}>
+      <Dropdown
+        trigger="click"
+        render={
+          <Dropdown.Menu>
+            <Dropdown.Item disabled>1111</Dropdown.Item>
+            <Dropdown.Divider />
+            <Dropdown.Item selected={true}>
+              2222 What if the text is super long? Longer than whatever you've known
+            </Dropdown.Item>
+            <Dropdown.Item>It looks OK</Dropdown.Item>
+          </Dropdown.Menu>
+        }
+      >
+        <div>分割线</div>
+      </Dropdown>
+    </div>
 
-        <div style={style}>
-            <Dropdown
-                position="bottomRight"
-                render={
-                    <Dropdown.Menu>
-                        <Dropdown.Item>333</Dropdown.Item>
-                        <Dropdown.Item>44444</Dropdown.Item>
-                    </Dropdown.Menu>
-                }
-            >
-                hover bottomRight
-            </Dropdown>
-        </div>
+    <div style={style}>
+      <Dropdown
+        onVisibleChange={change}
+        render={
+          <Dropdown.Menu>
+            <Dropdown.Item>333</Dropdown.Item>
+            <Dropdown.Item>44444</Dropdown.Item>
+          </Dropdown.Menu>
+        }
+      >
+        hover
+      </Dropdown>
+    </div>
 
-        <div style={style}>
-            <Dropdown
-                position="bottomLeft"
-                render={
-                    <Dropdown.Menu>
-                        <Dropdown.Item>333</Dropdown.Item>
-                        <Dropdown.Item>44444</Dropdown.Item>
-                    </Dropdown.Menu>
-                }
-            >
-                hover bottomLeft
-            </Dropdown>
-        </div>
+    <br />
 
-        {/* <div style={style}>
-       <Dropdown content="ies vigosss">
-           bottom hover
-       </Dropdown>
-    </div>
     <div style={style}>
-       <Dropdown trigger="click" content="ies vigo" trigger="click">
-           bottom click
-       </Dropdown>
+      <Dropdown
+        position="bottomRight"
+        render={
+          <Dropdown.Menu>
+            <Dropdown.Item>333</Dropdown.Item>
+            <Dropdown.Item>44444</Dropdown.Item>
+          </Dropdown.Menu>
+        }
+      >
+        hover bottomRight
+      </Dropdown>
     </div>
+
     <div style={style}>
-       <Dropdown content={<Button type="warning">btn</Button>}  trigger="click">
-           content is Node
-       </Dropdown>
-    </div> */}
+      <Dropdown
+        position="bottomLeft"
+        render={
+          <Dropdown.Menu>
+            <Dropdown.Item>333</Dropdown.Item>
+            <Dropdown.Item>44444</Dropdown.Item>
+          </Dropdown.Menu>
+        }
+      >
+        hover bottomLeft
+      </Dropdown>
     </div>
-));
-stories.add('Dropdown 2', () => {
-    return (
-        <div>
-            <Dropdown
-                trigger="click"
-                position="bottomLeft"
-                render={
-                    <Dropdown.Menu>
-                        <Dropdown.Item disabled>1111</Dropdown.Item>
-                        <Dropdown.Divider />
-                        <Dropdown.Item selected={true}>
-                            2222 What if the text is super long? Longer than whatever you've known
-                        </Dropdown.Item>
-                        <Dropdown.Item>It looks OK</Dropdown.Item>
-                    </Dropdown.Menu>
-                }
-            >
-                <Button>Open dropdown</Button>
-            </Dropdown>
-        </div>
-    );
-});
-stories.add('Avatar', () => {
-    return (
+  </div>
+);
+
+export const Dropdown2 = () => {
+  return (
+    <div>
+      <Dropdown
+        trigger="click"
+        position="bottomLeft"
+        render={
+          <Dropdown.Menu>
+            <Dropdown.Item disabled>1111</Dropdown.Item>
+            <Dropdown.Divider />
+            <Dropdown.Item selected={true}>
+              2222 What if the text is super long? Longer than whatever you've known
+            </Dropdown.Item>
+            <Dropdown.Item>It looks OK</Dropdown.Item>
+          </Dropdown.Menu>
+        }
+      >
+        <Button>Open dropdown</Button>
+      </Dropdown>
+    </div>
+  );
+};
+
+export const AvatarDemo = () => {
+  return (
+    <div
+      style={{
+        display: 'flex',
+        flexDirection: 'row-reverse',
+      }}
+    >
+      <Dropdown
+        autoAdjustOverflow={true}
+        trigger="click"
+        position="bottomRight"
+        getPopupContainer={() => document.querySelector('#dropdown-container')}
+        render={
+          <Dropdown.Menu>
+            <Dropdown.Item disabled>1111</Dropdown.Item>
+            <Dropdown.Divider />
+            <Dropdown.Item selected={true}>
+              2222 What if the text is super long? Longer than whatever you've known
+            </Dropdown.Item>
+            <Dropdown.Item>It looks OK</Dropdown.Item>
+          </Dropdown.Menu>
+        }
+      >
         <div
-            style={{
-                display: 'flex',
-                flexDirection: 'row-reverse',
-            }}
+          style={{
+            display: 'inline-block',
+          }}
         >
-            <Dropdown
-                autoAdjustOverflow={true}
-                trigger="click"
-                position="bottomRight"
-                getPopupContainer={() => document.querySelector('#dropdown-container')}
-                render={
-                    <Dropdown.Menu>
-                        <Dropdown.Item disabled>1111</Dropdown.Item>
-                        <Dropdown.Divider />
-                        <Dropdown.Item selected={true}>
-                            2222 What if the text is super long? Longer than whatever you've known
-                        </Dropdown.Item>
-                        <Dropdown.Item>It looks OK</Dropdown.Item>
-                    </Dropdown.Menu>
-                }
-            >
-                <div
-                    style={{
-                        display: 'inline-block',
-                    }}
-                >
-                    <Avatar size="small" src="" />
-                    <IconChevronDown />
-                </div>
-            </Dropdown>
-            <div id="dropdown-container" />
-        </div>
-    );
-});
-stories.add('Dropdown onVisibleChange', () => {
-    return (
-        <div>
-            <Dropdown
-                trigger="click"
-                onVisibleChange={(...args) => {
-                    console.log('onVisibleChange: ', ...args);
-                }}
-                render={
-                    <Dropdown.Menu>
-                        <Dropdown.Item disabled>1111</Dropdown.Item>
-                        <Dropdown.Divider />
-                        <Dropdown.Item selected={true}>
-                            2222 What if the text is super long? Longer than whatever you've known
-                        </Dropdown.Item>
-                        <Dropdown.Item>It looks OK</Dropdown.Item>
-                    </Dropdown.Menu>
-                }
-            >
-                <Button>Open dropdown</Button>
-            </Dropdown>
+          <Avatar size="small" src="" />
+          <IconChevronDown />
         </div>
-    );
-});
-stories.add('dropdown in table', () => <InTableDemo />);
-stories.add('dropdown auto close when clicked', () => <AutoClose />);
-stories.add('multi dropdown', () => <MultiDropdown />);
-stories.add('dropdownItem type', () => (
-    <>
-        <Dropdown
-            visible={true}
-            trigger="custom"
-            render={
-                <Dropdown.Menu>
-                    <Dropdown.Item type="primary">primary</Dropdown.Item>
-                    <Dropdown.Item type="secondary">secondary</Dropdown.Item>
-                    <Dropdown.Item type="tertiary">tertiary</Dropdown.Item>
-                    <Dropdown.Item type="warning">warning</Dropdown.Item>
-                    <Dropdown.Item type="danger">danger</Dropdown.Item>
-                    <Dropdown.Item>default</Dropdown.Item>
-                </Dropdown.Menu>
-            }
-        >
-            Different type Item
-        </Dropdown>
-        <Dropdown
-            visible={true}
-            trigger="custom"
-            showTick
-            render={
-                <Dropdown.Menu>
-                    <Dropdown.Item type="primary" active>
-                        primary
-                    </Dropdown.Item>
-                    <Dropdown.Item type="secondary">secondary</Dropdown.Item>
-                    <Dropdown.Item type="tertiary">tertiary</Dropdown.Item>
-                    <Dropdown.Item type="warning">warning</Dropdown.Item>
-                    <Dropdown.Item type="danger" active>
-                        编辑danger
-                    </Dropdown.Item>
-                    <Dropdown.Item>default</Dropdown.Item>
-                </Dropdown.Menu>
-            }
-        >
-            Different type Item
-        </Dropdown>
-    </>
-));
-stories.add('DisabledItem', () => <DisabledItem />);
-stories.add(`in hover elements`, () => <InHoverElements />);
-stories.add(`wrap avatar`, () => <WrapAvatar />);
+      </Dropdown>
+      <div id="dropdown-container" />
+    </div>
+  );
+};
+
+export const DropdownOnVisibleChange = () => {
+  return (
+    <div>
+      <Dropdown
+        trigger="click"
+        onVisibleChange={(...args) => {
+          console.log('onVisibleChange: ', ...args);
+        }}
+        render={
+          <Dropdown.Menu>
+            <Dropdown.Item disabled>1111</Dropdown.Item>
+            <Dropdown.Divider />
+            <Dropdown.Item selected={true}>
+              2222 What if the text is super long? Longer than whatever you've known
+            </Dropdown.Item>
+            <Dropdown.Item>It looks OK</Dropdown.Item>
+          </Dropdown.Menu>
+        }
+      >
+        <Button>Open dropdown</Button>
+      </Dropdown>
+    </div>
+  );
+};
+
+export const DropdownAutoCloseWhenClicked = () => <AutoClose />;
+
+DropdownAutoCloseWhenClicked.story = {
+  name: 'dropdown auto close when clicked',
+};
+
+export const DropdownItemType = () => (
+  <>
+    <Dropdown
+      visible={true}
+      trigger="custom"
+      render={
+        <Dropdown.Menu>
+          <Dropdown.Item type="primary">primary</Dropdown.Item>
+          <Dropdown.Item type="secondary">secondary</Dropdown.Item>
+          <Dropdown.Item type="tertiary">tertiary</Dropdown.Item>
+          <Dropdown.Item type="warning">warning</Dropdown.Item>
+          <Dropdown.Item type="danger">danger</Dropdown.Item>
+          <Dropdown.Item>default</Dropdown.Item>
+        </Dropdown.Menu>
+      }
+    >
+      Different type Item
+    </Dropdown>
+    <Dropdown
+      visible={true}
+      trigger="custom"
+      showTick
+      render={
+        <Dropdown.Menu>
+          <Dropdown.Item type="primary" active>
+            primary
+          </Dropdown.Item>
+          <Dropdown.Item type="secondary">secondary</Dropdown.Item>
+          <Dropdown.Item type="tertiary">tertiary</Dropdown.Item>
+          <Dropdown.Item type="warning">warning</Dropdown.Item>
+          <Dropdown.Item type="danger" active>
+            编辑danger
+          </Dropdown.Item>
+          <Dropdown.Item>default</Dropdown.Item>
+        </Dropdown.Menu>
+      }
+    >
+      Different type Item
+    </Dropdown>
+  </>
+);
 
-function DropdownItemPropsDemo() {
-    return (
-        <div>
-            <Dropdown
-                trigger="custom"
-                position="bottomLeft"
-                visible
-                render={
-                    <Dropdown.Menu>
-                        <Dropdown.Item icon={<IconBox />}>Menu Item 1</Dropdown.Item>
-                        <Dropdown.Item iconType="setting">Menu Item 2</Dropdown.Item>
-                        <Dropdown.Item disabled iconType="forward">
-                            Menu Item 3
-                        </Dropdown.Item>
-                        <Dropdown.Item iconType="align_center" type="primary" iconType="branch">
-                            primary
-                        </Dropdown.Item>
-                        <Dropdown.Item iconType="color_palette" type="secondary">
-                            secondary
-                        </Dropdown.Item>
-                        <Dropdown.Item iconType="refresh" type="tertiary">
-                            tertiary
-                        </Dropdown.Item>
-                        <Dropdown.Item iconType="search" type="warning">
-                            warning
-                        </Dropdown.Item>
-                        <Dropdown.Item
-                            icon={
-                                <IconSimiarlity
-                                    style={{
-                                        color: 'var(--semi-color-tertiary)',
-                                    }}
-                                />
-                            }
-                            type="danger"
-                        >
-                            danger
-                        </Dropdown.Item>
-                    </Dropdown.Menu>
-                }
+export function DropdownItemPropsDemo() {
+  return (
+    <div>
+      <Dropdown
+        trigger="custom"
+        position="bottomLeft"
+        visible
+        render={
+          <Dropdown.Menu>
+            <Dropdown.Item icon={<IconBox />}>Menu Item 1</Dropdown.Item>
+            <Dropdown.Item iconType="setting">Menu Item 2</Dropdown.Item>
+            <Dropdown.Item disabled iconType="forward">
+              Menu Item 3
+            </Dropdown.Item>
+            <Dropdown.Item iconType="align_center" type="primary" iconType="branch">
+              primary
+            </Dropdown.Item>
+            <Dropdown.Item iconType="color_palette" type="secondary">
+              secondary
+            </Dropdown.Item>
+            <Dropdown.Item iconType="refresh" type="tertiary">
+              tertiary
+            </Dropdown.Item>
+            <Dropdown.Item iconType="search" type="warning">
+              warning
+            </Dropdown.Item>
+            <Dropdown.Item
+              icon={
+                <IconSimilarity
+                  style={{
+                    color: 'var(--semi-color-tertiary)',
+                  }}
+                />
+              }
+              type="danger"
             >
-                <Button>始终展示</Button>
-            </Dropdown>
-            <Dropdown
-                trigger="custom"
-                position="bottomLeft"
-                showTick
-                visible
-                render={
-                    <Dropdown.Menu>
-                        <Dropdown.Item active icon={<IconBox />}>
-                            Menu Item 1
-                        </Dropdown.Item>
-                        <Dropdown.Item iconType="setting">Menu Item 2</Dropdown.Item>
-                        <Dropdown.Item disabled iconType="forward">
-                            Menu Item 3
-                        </Dropdown.Item>
-                        <Dropdown.Item iconType="align_center" type="primary" iconType="branch">
-                            primary
-                        </Dropdown.Item>
-                        <Dropdown.Item iconType="color_palette" type="secondary">
-                            secondary
-                        </Dropdown.Item>
-                        <Dropdown.Item iconType="refresh" type="tertiary">
-                            tertiary
-                        </Dropdown.Item>
-                        <Dropdown.Item iconType="search" type="warning">
-                            warning
-                        </Dropdown.Item>
-                        <Dropdown.Item
-                            icon={
-                                <IconSimiarlity
-                                    style={{
-                                        color: 'var(--semi-color-tertiary)',
-                                    }}
-                                />
-                            }
-                            type="danger"
-                        >
-                            danger
-                        </Dropdown.Item>
-                    </Dropdown.Menu>
-                }
+              danger
+            </Dropdown.Item>
+          </Dropdown.Menu>
+        }
+      >
+        <Button>始终展示</Button>
+      </Dropdown>
+      <Dropdown
+        trigger="custom"
+        position="bottomLeft"
+        showTick
+        visible
+        render={
+          <Dropdown.Menu>
+            <Dropdown.Item active icon={<IconBox />}>
+              Menu Item 1
+            </Dropdown.Item>
+            <Dropdown.Item iconType="setting">Menu Item 2</Dropdown.Item>
+            <Dropdown.Item disabled iconType="forward">
+              Menu Item 3
+            </Dropdown.Item>
+            <Dropdown.Item iconType="align_center" type="primary" iconType="branch">
+              primary
+            </Dropdown.Item>
+            <Dropdown.Item iconType="color_palette" type="secondary">
+              secondary
+            </Dropdown.Item>
+            <Dropdown.Item iconType="refresh" type="tertiary">
+              tertiary
+            </Dropdown.Item>
+            <Dropdown.Item iconType="search" type="warning">
+              warning
+            </Dropdown.Item>
+            <Dropdown.Item
+              icon={
+                <IconSimilarity
+                  style={{
+                    color: 'var(--semi-color-tertiary)',
+                  }}
+                />
+              }
+              type="danger"
             >
-                <Button
-                    style={{
-                        marginLeft: 200,
-                    }}
-                >
-                    始终展示
-                </Button>
-            </Dropdown>
-        </div>
-    );
-}
-
-stories.add(`Dropdown.Item props`, () => <DropdownItemPropsDemo />);
+              danger
+            </Dropdown.Item>
+          </Dropdown.Menu>
+        }
+      >
+        <Button
+          style={{
+            marginLeft: 200,
+          }}
+        >
+          始终展示
+        </Button>
+      </Dropdown>
+    </div>
+  );
+}

+ 44 - 40
packages/semi-ui/empty/_story/empty.stories.js

@@ -1,49 +1,53 @@
 import React from 'react';
-import { storiesOf } from '@storybook/react';
-// import { withKnobs, text, boolean } from '@storybook/addon-knobs';
 
 import Empty from '../index';
 import Button from '../../button';
 import { IllustrationSuccess } from '@douyinfe/semi-illustrations';
 
-const stories = storiesOf('Empty', module);
+export default {
+  title: 'Empty',
+}
 
-stories.add('empty simple', () => (
-    <div>
-        <Empty image={Success} description={'功能建设中'} />
-        <br />
-        <Empty image={Success} description={'功能建设中'}>
-            该模块功能建设中,敬请期待。该模块功能建设中,敬请期待。
-        </Empty>
-        <br />
-        <Empty image={Success}>该模块功能建设中,敬请期待。该模块功能建设中,敬请期待。</Empty>
-        <br />
-        <Empty description={'功能建设中'}>该模块功能建设中,敬请期待。该模块功能建设中,敬请期待。</Empty>
-    </div>
-));
+export const EmptySimple = () => (
+  <div>
+    <Empty image={<IllustrationSuccess />} description={'功能建设中'} />
+    <br />
+    <Empty image={<IllustrationSuccess />} description={'功能建设中'}>
+      该模块功能建设中,敬请期待。该模块功能建设中,敬请期待。
+    </Empty>
+    <br />
+    <Empty image={<IllustrationSuccess />}>
+      该模块功能建设中,敬请期待。该模块功能建设中,敬请期待。
+    </Empty>
+    <br />
+    <Empty description={'功能建设中'}>
+      该模块功能建设中,敬请期待。该模块功能建设中,敬请期待。
+    </Empty>
+  </div>
+);
 
-stories.add('empty cta', () => (
-    <div>
-        <Empty description={'功能建设中'} image={<IllustrationSuccess />}>
-            <div style={{ textAlign: 'center' }}>
-                <p>该模块功能建设中,敬请期待。该模块功能建设中,敬请期待。</p>
-                <Button type="primary" style={{ marginTop: 24 }}>
-                    建设中
-                </Button>
-            </div>
-        </Empty>
-    </div>
-));
+export const EmptyCta = () => (
+  <div>
+    <Empty description={'功能建设中'} image={<IllustrationSuccess />}>
+      <div style={{ textAlign: 'center' }}>
+        <p>该模块功能建设中,敬请期待。该模块功能建设中,敬请期待。</p>
+        <Button type="primary" style={{ marginTop: 24 }}>
+          建设中
+        </Button>
+      </div>
+    </Empty>
+  </div>
+);
 
-stories.add('empty layout', () => (
-    <div>
-        <Empty description={'功能建设中'} image={<IllustrationSuccess />} layout="horizontal">
-            <div>
-                <p>该模块功能建设中,敬请期待。该模块功能建设中,敬请期待。</p>
-                <Button type="primary" style={{ marginTop: 24 }}>
-                    建设中
-                </Button>
-            </div>
-        </Empty>
-    </div>
-));
+export const EmptyLayout = () => (
+  <div>
+    <Empty description={'功能建设中'} image={<IllustrationSuccess />} layout="horizontal">
+      <div>
+        <p>该模块功能建设中,敬请期待。该模块功能建设中,敬请期待。</p>
+        <Button type="primary" style={{ marginTop: 24 }}>
+          建设中
+        </Button>
+      </div>
+    </Empty>
+  </div>
+);

+ 442 - 188
packages/semi-ui/form/_story/form.stories.js

@@ -1,30 +1,51 @@
 import React, { useState, useLayoutEffect, useEffect, useRef } from 'react';
-import { storiesOf } from '@storybook/react';
-import { Button, Modal, TreeSelect, Row, Col, Avatar, Tabs, TabPane, Badge, Notification } from '../../index';
 import {
-    Form,
-    useFormState,
-    useFormApi,
-    useFieldApi,
-    useFieldState,
-    withFormState,
-    withFormApi,
-    withField,
-    ArrayField,
-    Icon,
+  Button,
+  Modal,
+  TreeSelect,
+  Row,
+  Col,
+  Avatar,
+  Tabs,
+  TabPane,
+  Badge,
+  Notification,
+} from '../../index';
+import {
+  Form,
+  useFormState,
+  useFormApi,
+  useFieldApi,
+  useFieldState,
+  withFormState,
+  withFormApi,
+  withField,
+  ArrayField,
+  Icon,
 } from '../../index';
 import { BasicDemoWithInit, LinkFieldForm, I18nDemo, DifferentDeclareUsage } from './demo';
-const { Input, Select, DatePicker, Switch, Slider, CheckboxGroup, Checkbox, RadioGroup, Radio, TimePicker } = Form;
+const {
+  Input,
+  Select,
+  DatePicker,
+  Switch,
+  Slider,
+  CheckboxGroup,
+  Checkbox,
+  RadioGroup,
+  Radio,
+  TimePicker,
+} = Form;
 
 import {
-    UseFormApiDemo,
-    UseFormStateDemo,
-    UseFieldApiDemo,
-    UseFieldStateDemo,
-    WithFormStateDemo,
-    WithFormApiDemo,
-    ComponentUsingFormState,
-    CustomStringify,
+  UseFormApiDemo,
+  UseFormStateDemo,
+  UseFieldApiDemo,
+  UseFieldStateDemo,
+  WithFormStateDemo,
+  WithFormApiDemo,
+  ComponentUsingFormState,
+  CustomStringify,
 } from './Hook/hookDemo';
 
 // layout
@@ -34,7 +55,15 @@ import { ModalFormDemo } from './Layout/modalFormDemo';
 
 import { WithFieldDemo, CustomFieldDemo, NumberRange } from './HOC/withFieldDemo';
 import { WithDisplayName } from './HOC/displayName';
-import { CustomValidateDemo, ValidateFieldsDemo, PartValidAndResetDemo, RulesValidateDemo, SetBugDemo, UnmountedLeafDemo, RulesExample } from './Validate/validateDemo';
+import {
+  CustomValidateDemo,
+  ValidateFieldsDemo,
+  PartValidAndResetDemo,
+  RulesValidateDemo,
+  SetBugDemo,
+  UnmountedLeafDemo,
+  RulesExample,
+} from './Validate/validateDemo';
 
 // field props
 import { ConvertDemo } from './FieldProps/convert';
@@ -45,208 +74,433 @@ import { FieldRefDemo } from './FieldProps/fieldRef';
 
 // arrayField
 import {
-    ArrayFieldCollapseDemo,
-    ArrayFieldDemo,
-    ArrayFieldWithFormInitValues,
-    ArrayFieldWithInitValue,
+  ArrayFieldCollapseDemo,
+  ArrayFieldDemo,
+  ArrayFieldWithFormInitValues,
+  ArrayFieldWithInitValue,
 } from './DynamicField/arrayFieldDemo';
 import { NestArrayField } from './DynamicField/nestArrayField';
 import { ArrayDemo } from './FormApi/arrayDemo';
 
 // performance
-import { ManyFieldDemo, EffectDemo, ModalFormSelectWithObject } from './Performance/performanceDemo';
+import {
+  ManyFieldDemo,
+  EffectDemo,
+  ModalFormSelectWithObject,
+} from './Performance/performanceDemo';
 import { SetValuesDemo, SetValuesWithArrayField } from './FormApi/setValuesDemo';
 import { SetValueUsingParentPath } from './FormApi/formApiDemo';
 import { FieldPathWithArrayDemo } from './Debug/bugDemo';
 import ChildDidMount from './Debug/childDidMount';
 
-const stories = storiesOf('Form', module);
+export default {
+  title: 'Form'
+}
+
 const Option = Select.Option;
 
-stories.add('Form declare usage', () => <DifferentDeclareUsage />);
-stories.add('BasicDemo', () => <BasicDemoWithInit />);
+export const FormDeclareUsage = () => <DifferentDeclareUsage />;
 
-stories.add('Layout-Form.InputGroup', () => <GroupFormDemo />);
-stories.add('Layout-Form wrapperCol/labelCol', () => <LayoutDemo />);
-stories.add('Layout-insetLabel', () => <InsetLabelDemo />);
-stories.add('Layout-Slot/ErrorMessage/Label', () => <AssistComponent />);
-stories.add('Layout- ModalDemo', () => <ModalFormDemo />);
+FormDeclareUsage.story = {
+  name: 'Form declare usage',
+};
 
-stories.add('formApi-setValues(override)', () => <SetValuesDemo />);
-stories.add('formApi-validate', () => <PartValidAndResetDemo />);
-stories.add('formApi-setValue using field parent path', () => <SetValueUsingParentPath />);
+export const BasicDemo = () => <BasicDemoWithInit />;
 
-stories.add('Dynamic Add / Remove Field', () => (
-    <Form>
-        {({ formState }) => (
-            <React.Fragment>
-                <Input field="name" label="First name:" />
-                <RadioGroup field="married" label="Are you married?">
-                    <Radio value="yes">yes</Radio>
-                    <Radio value="no">no</Radio>
-                </RadioGroup>
-                {formState.values.married === 'yes' ? <Input field="spouse" label="Spouse name:" /> : null}
-                <Button htmlType="submit">Submit</Button>
-                <ComponentUsingFormState />
-            </React.Fragment>
-        )}
-    </Form>
-));
+BasicDemo.story = {
+  name: 'BasicDemo',
+};
 
-stories.add('ArrayField-basic usage', () => <ArrayFieldDemo />);
-stories.add('ArrayField-with form initValues', () => <ArrayFieldWithFormInitValues />);
-stories.add('ArrayField-with arrayField initValue', () => <ArrayFieldWithInitValue />);
-stories.add('ArrayField-Nest Usage', () => <NestArrayField />);
-stories.add('ArrayField-CollapseDemo', () => <ArrayFieldCollapseDemo />);
+export const LayoutFormInputGroup = () => <GroupFormDemo />;
+
+LayoutFormInputGroup.story = {
+  name: 'Layout-Form.InputGroup',
+};
 
-stories.add('【数组】动态增删表单项-使用FormState、FormApi手动处理', () => <ArrayDemo />);
+export const LayoutFormWrapperColLabelCol = () => <LayoutDemo />;
 
-stories.add('LinkField', () => <LinkFieldForm />);
-stories.add('Validate-FormLevel', () => <ValidateFieldsDemo />);
-stories.add('Validate-FieldValel', () => <CustomValidateDemo />);
-stories.add('Validate-use rules', () => <RulesValidateDemo />);
+LayoutFormWrapperColLabelCol.story = {
+  name: 'Layout-Form wrapperCol/labelCol',
+};
 
-stories.add('Hooks-useFormApi', () => <UseFormApiDemo />);
-stories.add('Hooks-useFormState', () => <UseFormStateDemo />);
-stories.add('Hooks-useFieldApi', () => <UseFieldApiDemo />);
-stories.add('Hooks-useFieldState', () => <UseFieldStateDemo />);
+export const LayoutInsetLabel = () => <InsetLabelDemo />;
 
-stories.add('Hoc-withFormApi', () => <WithFormApiDemo />);
-stories.add('Hoc-withFormState', () => <WithFormStateDemo />);
+LayoutInsetLabel.story = {
+  name: 'Layout-insetLabel',
+};
 
-// stories.add('Hoc-withFieldApi', () => (<div></div>));
-// stories.add('Hoc-withFieldState', () => (<div></div>));
+export const LayoutSlotErrorMessageLabel = () => <AssistComponent />;
 
-stories.add('withField', () => <CustomFieldDemo />);
-stories.add('withField- with stateful component', () => <WithFieldDemo />);
-stories.add('withField - NumberRange', () => (
-    <Form onChange={v => console.log(v)}>
-        <NumberRange field="number" initValue={[1, 2]} noLabel={true}></NumberRange>
-    </Form>
-));
-
-stories.add('Performance-ManyField', () => <ManyFieldDemo />);
-stories.add('Performance-ModalFormSelectWithObject', () => <ModalFormSelectWithObject />);
-
-stories.add('Filed Prop-convert', () => <ConvertDemo />);
-stories.add('Filed Prop-helpText / extraText / extraTextPosition', () => (
-    <>
-        <HelpAndExtra />
-        <ExtraPositionDemo />
-        <GroupFormDemo />
-    </>
-));
-stories.add('Field Props-dynamic update rules.required', () => <RuleupdateDemo />);
-stories.add('Field Prop-initValue=""', () => <InitEmptyStringDemo />);
-stories.add('Field prop-big number field submit', () => <BigNumberFieldDemo />);
-stories.add('Field Prop-pure', () => (
-    <Form>
-        <Form.Select field="name" pure className="fefefe" fieldClassName="feichang" style={{ width: 400 }} />
-    </Form>
-));
-stories.add('Field Prop-ref', () => <FieldRefDemo />);
+LayoutSlotErrorMessageLabel.story = {
+  name: 'Layout-Slot/ErrorMessage/Label',
+};
+
+export const LayoutModalDemo = () => <ModalFormDemo />;
+
+LayoutModalDemo.story = {
+  name: 'Layout- ModalDemo',
+};
+
+export const FormApiSetValuesOverride = () => <SetValuesDemo />;
+
+FormApiSetValuesOverride.story = {
+  name: 'formApi-setValues(override)',
+};
+
+export const FormApiValidate = () => <PartValidAndResetDemo />;
+
+FormApiValidate.story = {
+  name: 'formApi-validate',
+};
+
+export const FormApiSetValueUsingFieldParentPath = () => <SetValueUsingParentPath />;
+
+FormApiSetValueUsingFieldParentPath.story = {
+  name: 'formApi-setValue using field parent path',
+};
+
+export const DynamicAddRemoveField = () => (
+  <Form>
+    {({ formState }) => (
+      <React.Fragment>
+        <Input field="name" label="First name:" />
+        <RadioGroup field="married" label="Are you married?">
+          <Radio value="yes">yes</Radio>
+          <Radio value="no">no</Radio>
+        </RadioGroup>
+        {formState.values.married === 'yes' ? <Input field="spouse" label="Spouse name:" /> : null}
+        <Button htmlType="submit">Submit</Button>
+        <ComponentUsingFormState />
+      </React.Fragment>
+    )}
+  </Form>
+);
+
+DynamicAddRemoveField.story = {
+  name: 'Dynamic Add / Remove Field',
+};
+
+export const ArrayFieldBasicUsage = () => <ArrayFieldDemo />;
+
+ArrayFieldBasicUsage.story = {
+  name: 'ArrayField-basic usage',
+};
+
+export const _ArrayFieldWithFormInitValues = () => <ArrayFieldWithFormInitValues />;
+
+_ArrayFieldWithFormInitValues.story = {
+  name: 'ArrayField-with form initValues',
+};
+
+export const ArrayFieldWithArrayFieldInitValue = () => <ArrayFieldWithInitValue />;
+
+ArrayFieldWithArrayFieldInitValue.story = {
+  name: 'ArrayField-with arrayField initValue',
+};
+
+export const ArrayFieldNestUsage = () => <NestArrayField />;
+
+ArrayFieldNestUsage.story = {
+  name: 'ArrayField-Nest Usage',
+};
+
+export const _ArrayFieldCollapseDemo = () => <ArrayFieldCollapseDemo />;
+
+_ArrayFieldCollapseDemo.story = {
+  name: 'ArrayField-CollapseDemo',
+};
+
+export const ArrayFieldDynamicUpdate = () => <ArrayDemo />;
+
+ArrayFieldDynamicUpdate.story = {
+  name: 'ArrayField-dynamic update',
+};
+
+export const LinkField = () => <LinkFieldForm />;
+
+LinkField.story = {
+  name: 'LinkField',
+};
+
+export const ValidateFormLevel = () => <ValidateFieldsDemo />;
+
+ValidateFormLevel.story = {
+  name: 'Validate-FormLevel',
+};
+
+export const ValidateFieldValel = () => <CustomValidateDemo />;
+
+ValidateFieldValel.story = {
+  name: 'Validate-FieldValel',
+};
+
+export const ValidateUseRules = () => <RulesValidateDemo />;
+
+ValidateUseRules.story = {
+  name: 'Validate-use rules',
+};
+
+export const HooksUseFormApi = () => <UseFormApiDemo />;
+
+HooksUseFormApi.story = {
+  name: 'Hooks-useFormApi',
+};
+
+export const HooksUseFormState = () => <UseFormStateDemo />;
+
+HooksUseFormState.story = {
+  name: 'Hooks-useFormState',
+};
+
+export const HooksUseFieldApi = () => <UseFieldApiDemo />;
+
+HooksUseFieldApi.story = {
+  name: 'Hooks-useFieldApi',
+};
+
+export const HooksUseFieldState = () => <UseFieldStateDemo />;
+
+HooksUseFieldState.story = {
+  name: 'Hooks-useFieldState',
+};
+
+export const HocWithFormApi = () => <WithFormApiDemo />;
+
+HocWithFormApi.story = {
+  name: 'Hoc-withFormApi',
+};
+
+export const HocWithFormState = () => <WithFormStateDemo />;
+
+HocWithFormState.story = {
+  name: 'Hoc-withFormState',
+};
+
+export const WithField = () => <CustomFieldDemo />;
+
+WithField.story = {
+  name: 'withField',
+};
+
+export const WithFieldWithStatefulComponent = () => <WithFieldDemo />;
+
+WithFieldWithStatefulComponent.story = {
+  name: 'withField- with stateful component',
+};
+
+export const WithFieldNumberRange = () => (
+  <Form onChange={v => console.log(v)}>
+    <NumberRange field="number" initValue={[1, 2]} noLabel={true}></NumberRange>
+  </Form>
+);
+
+WithFieldNumberRange.story = {
+  name: 'withField - NumberRange',
+};
+
+export const PerformanceManyField = () => <ManyFieldDemo />;
+
+PerformanceManyField.story = {
+  name: 'Performance-ManyField',
+};
+
+export const PerformanceModalFormSelectWithObject = () => <ModalFormSelectWithObject />;
+
+PerformanceModalFormSelectWithObject.story = {
+  name: 'Performance-ModalFormSelectWithObject',
+};
+
+export const FiledPropConvert = () => <ConvertDemo />;
+
+FiledPropConvert.story = {
+  name: 'Filed Prop-convert',
+};
+
+export const FiledPropHelpTextExtraTextExtraTextPosition = () => (
+  <>
+    <HelpAndExtra />
+    <ExtraPositionDemo />
+    <GroupFormDemo />
+  </>
+);
+
+FiledPropHelpTextExtraTextExtraTextPosition.story = {
+  name: 'Filed Prop-helpText / extraText / extraTextPosition',
+};
+
+export const FieldPropsDynamicUpdateRulesRequired = () => <RuleupdateDemo />;
+
+FieldPropsDynamicUpdateRulesRequired.story = {
+  name: 'Field Props-dynamic update rules.required',
+};
+
+export const FieldPropInitValue = () => <InitEmptyStringDemo />;
+
+FieldPropInitValue.story = {
+  name: 'Field Prop-initValue=""',
+};
+
+export const FieldPropBigNumberFieldSubmit = () => <BigNumberFieldDemo />;
+
+FieldPropBigNumberFieldSubmit.story = {
+  name: 'Field prop-big number field submit',
+};
+
+export const FieldPropPure = () => (
+  <Form>
+    <Form.Select
+      field="name"
+      pure
+      className="fefefe"
+      fieldClassName="feichang"
+      style={{ width: 400 }}
+    />
+  </Form>
+);
+
+FieldPropPure.story = {
+  name: 'Field Prop-pure',
+};
+
+export const FieldPropRef = () => <FieldRefDemo />;
+
+FieldPropRef.story = {
+  name: 'Field Prop-ref',
+};
 
 const InitEmptyStringDemo = () => {
-    return (
-        <Form allowEmpty>
-            <Form.Input field="name" initValue="" />
-            <ComponentUsingFormState />
-        </Form>
-    );
+  return (
+    <Form allowEmpty>
+      <Form.Input field="name" initValue="" />
+      <ComponentUsingFormState />
+    </Form>
+  );
 };
 
+export const DebugSetBugDemo = () => (
+  <>
+    <SetBugDemo />
+    <UnmountedLeafDemo />
+  </>
+);
+
+DebugSetBugDemo.story = {
+  name: 'Debug-SetBugDemo',
+};
 
-stories.add('Debug-SetBugDemo', () => (
-    <>
-        <SetBugDemo />
-        <UnmountedLeafDemo />
-    </>
-));
+export const DebugSetValuesWithArrayField = () => (
+  <>
+    <SetValuesWithArrayField />
+  </>
+);
 
-stories.add('Debug-SetValuesWithArrayField', () => (
-    <>
-        <SetValuesWithArrayField />
-    </>
-));
+DebugSetValuesWithArrayField.story = {
+  name: 'Debug-SetValuesWithArrayField',
+};
 
 import { SetValuesArray, DoubleRerender } from './Debug/bugDemo';
 
-stories.add('Debug-数组类fieldPath', () => <FieldPathWithArrayDemo />);
+export const DebugArrayFieldPath = () => <FieldPathWithArrayDemo />;
 
-stories.add('Debug-SetValuesDemo', () => (
-    <>
-        <SetValuesArray />
-    </>
-));
+DebugArrayFieldPath.story = {
+  name: 'Debug-数组类fieldPath',
+};
 
-// useFormState与rules使用时,会rerender两次
-stories.add('Debug-RerenderTwice', () => (
-    <>
-        <DoubleRerender />
-    </>
-));
+export const DebugSetValuesDemo = () => (
+  <>
+    <SetValuesArray />
+  </>
+);
+
+DebugSetValuesDemo.story = {
+  name: 'Debug-SetValuesDemo',
+};
 
-stories.add('Field displayName', () => <WithDisplayName attr="form" />);
+export const DebugRerenderTwice = () => (
+  <>
+    <DoubleRerender />
+  </>
+);
+
+DebugRerenderTwice.story = {
+  name: 'Debug-RerenderTwice',
+};
+
+export const FieldDisplayName = () => <WithDisplayName attr="form" />;
+
+FieldDisplayName.story = {
+  name: 'Field displayName',
+};
 
 class ReUseDemo extends React.Component {
-    constructor() {
-        super();
-        this.getFormApi = this.getFormApi.bind(this);
-        this.suppressRankOptions = [
-          { label: '不打压', value: 0 },
-          { label: 'top10以下', value: 10 },
-          { label: 'top30以下', value: 30 },
-        ];
-        this.citySuppressRankOptions = [
-          { label: '不打压', value: 0 },
-          { label: 'top3以下', value: 3 },
-          { label: 'top5以下', value: 5 },
-          { label: 'top10以下', value: 10 },
-        ];
-    }
-
-    getFormApi(formApi) { this.formApi = formApi; }
-
-    render() {
-        return (
-            <Form getFormApi={this.getFormApi} initValues={{ listType: 'online', attr: { suppress_rank: 0, city_suppress_rank: 5 }}} onValueChange={values => console.log(values) } style={{ width: 250 }}>
-                {({ formState }) => (<>
-                <Form.Select
-                    field="listType"
-                    label="榜单类型"
-                    disabled={this.ifUseOld}
-                    style={{ width: '100%' }}
-                    // onChange={val => this.onChangeListType(val)}
-                  >
-                    <Option value="online" >
-                      热点榜
-                    </Option>
-                    <Option value="riseHot" >
-                      上升热点榜
-                    </Option>
-                    <Option value="sameCity" >
-                      同城热点榜
-                    </Option>
-                  </Form.Select>
-                {formState.values.listType !== 'sameCity' ? (
-                    <Form.Select
-                      label="竞品打压类型"
-                      field="attr.suppress_rank"
-                      optionList={this.suppressRankOptions}
-                    />
-                ) : (
-                    <Form.Select
-                      label="同城竞品打压"
-                      field="attr.city_suppress_rank"
-                      optionList={this.citySuppressRankOptions}
-                    />
-                )}
-                </>)}
-            </Form>
-        );
-    }
+  constructor() {
+    super();
+    this.getFormApi = this.getFormApi.bind(this);
+    this.suppressRankOptions = [
+      { label: '不打压', value: 0 },
+      { label: 'top10以下', value: 10 },
+      { label: 'top30以下', value: 30 },
+    ];
+    this.citySuppressRankOptions = [
+      { label: '不打压', value: 0 },
+      { label: 'top3以下', value: 3 },
+      { label: 'top5以下', value: 5 },
+      { label: 'top10以下', value: 10 },
+    ];
+  }
+
+  getFormApi(formApi) {
+    this.formApi = formApi;
+  }
+
+  render() {
+    return (
+      <Form
+        getFormApi={this.getFormApi}
+        initValues={{ listType: 'online', attr: { suppress_rank: 0, city_suppress_rank: 5 } }}
+        onValueChange={values => console.log(values)}
+        style={{ width: 250 }}
+      >
+        {({ formState }) => (
+          <>
+            <Form.Select
+              field="listType"
+              label="榜单类型"
+              disabled={this.ifUseOld}
+              style={{ width: '100%' }}
+              // onChange={val => this.onChangeListType(val)}
+            >
+              <Option value="online">热点榜</Option>
+              <Option value="riseHot">上升热点榜</Option>
+              <Option value="sameCity">同城热点榜</Option>
+            </Form.Select>
+            {formState.values.listType !== 'sameCity' ? (
+              <Form.Select
+                label="竞品打压类型"
+                field="attr.suppress_rank"
+                optionList={this.suppressRankOptions}
+              />
+            ) : (
+              <Form.Select
+                label="同城竞品打压"
+                field="attr.city_suppress_rank"
+                optionList={this.citySuppressRankOptions}
+              />
+            )}
+          </>
+        )}
+      </Form>
+    );
+  }
 }
-stories.add('same field switch cause reuse', () => <ReUseDemo />);
+export const SameFieldSwitchCauseReuse = () => <ReUseDemo />;
+
+SameFieldSwitchCauseReuse.story = {
+  name: 'same field switch cause reuse',
+};
 
-stories.add('child didmount', () => <ChildDidMount />);
+export const _ChildDidMount = () => <ChildDidMount />;
 
+_ChildDidMount.story = {
+  name: 'child did mount',
+};

+ 283 - 223
packages/semi-ui/grid/_story/grid.stories.js

@@ -1,230 +1,290 @@
 import React from 'react';
-import { storiesOf } from '@storybook/react';
-// import { withKnobs, text, boolean } from '@storybook/addon-knobs';
 
 import './demo.scss';
 import { Col, Row } from '../index';
 
-const stories = storiesOf('Grid', module);
-
-// stories.addDecorator(withKnobs);;
-
-stories.add('grid default', () => (
-    <div>
-        <Row>
-            <Col span={24}>col-24</Col>
-        </Row>
-        <Row>
-            <Col span={12}>col-12</Col>
-            <Col span={12}>col-12</Col>
-        </Row>
-        <Row>
-            <Col span={8}>col-8</Col>
-            <Col span={8}>col-8</Col>
-            <Col span={8}>col-8</Col>
-        </Row>
-        <Row>
-            <Col span={6}>col-6</Col>
-            <Col span={6}>col-6</Col>
-            <Col span={6}>col-6</Col>
-            <Col span={6}>col-6</Col>
-        </Row>
-    </div>
-));
-
-stories.add('grid with gutter', () => (
-    <div className="gutter-example">
-        <p>横向间距16</p>
-        <hr/>
-        <Row gutter={16}>
-            <Col className="gutter-row" span={6}>
-                <div className="gutter-box">col-6</div>
-            </Col>
-            <Col className="gutter-row" span={6}>
-                <div className="gutter-box">col-6</div>
-            </Col>
-            <Col className="gutter-row" span={6}>
-                <div className="gutter-box">col-6</div>
-            </Col>
-            <Col className="gutter-row" span={6}>
-                <div className="gutter-box">col-6</div>
-            </Col>
-        </Row>
-        <p>横向间距16,纵向间距48</p>
-        <hr/>
-        <Row gutter={[16, 48]}>
-            <Col className="gutter-row" span={6}>
-                <div className="gutter-box">col-6</div>
-            </Col>
-            <Col className="gutter-row" span={6}>
-                <div className="gutter-box">col-6</div>
-            </Col>
-            <Col className="gutter-row" span={6}>
-                <div className="gutter-box">col-6</div>
-            </Col>
-            <Col className="gutter-row" span={6}>
-                <div className="gutter-box">col-6</div>
-            </Col>
-            <Col className="gutter-row" span={6}>
-                <div className="gutter-box">col-6</div>
-            </Col>
-            <Col className="gutter-row" span={6}>
-                <div className="gutter-box">col-6</div>
-            </Col>
-            <Col className="gutter-row" span={6}>
-                <div className="gutter-box">col-6</div>
-            </Col>
-            <Col className="gutter-row" span={6}>
-                <div className="gutter-box">col-6</div>
-            </Col>
-        </Row>
-        <p>横向间距16,纵向间距24</p>
-        <hr/>
-        <Row gutter={[16, 24]}>
-            <Col className="gutter-row" span={6}>
-                <div className="gutter-box">col-6</div>
-            </Col>
-            <Col className="gutter-row" span={6}>
-                <div className="gutter-box">col-6</div>
-            </Col>
-            <Col className="gutter-row" span={6}>
-                <div className="gutter-box">col-6</div>
-            </Col>
-            <Col className="gutter-row" span={6}>
-                <div className="gutter-box">col-6</div>
-            </Col>
-            <Col className="gutter-row" span={6}>
-                <div className="gutter-box">col-6</div>
-            </Col>
-            <Col className="gutter-row" span={6}>
-                <div className="gutter-box">col-6</div>
-            </Col>
-            <Col className="gutter-row" span={6}>
-                <div className="gutter-box">col-6</div>
-            </Col>
-            <Col className="gutter-row" span={6}>
-                <div className="gutter-box">col-6</div>
-            </Col>
-        </Row>
-    </div>
-));
-
-stories.add('grid with offset', () => (
-    <div>
-        <Row>
-            <Col span={8}>col-8</Col>
-            <Col span={8} offset={8}>col-8</Col>
-        </Row>
-        <Row>
-            <Col span={6} offset={6}>col-6 col-offset-6</Col>
-            <Col span={6} offset={6}>col-6 col-offset-6</Col>
-        </Row>
-        <Row>
-            <Col span={12} offset={6}>col-12 col-offset-6</Col>
-        </Row>
-    </div>
-));
-stories.add('grid with pull & push', () => (
-    <div>
-        <Row>
-            <Col span={18} push={6}>col-18 col-push-6</Col>
-            <Col span={6} pull={18}>col-6 col-pull-18</Col>
-        </Row>
-    </div>
-));
-stories.add('grid with type flex', () => (
-    <div>
-        <p>sub-element align left</p>
-        <Row type="flex" justify="start">
-            <Col span={4}>col-4</Col>
-            <Col span={4}>col-4</Col>
-            <Col span={4}>col-4</Col>
-            <Col span={4}>col-4</Col>
-        </Row>
-
-        <p>sub-element align center</p>
-        <Row type="flex" justify="center">
-            <Col span={4}>col-4</Col>
-            <Col span={4}>col-4</Col>
-            <Col span={4}>col-4</Col>
-            <Col span={4}>col-4</Col>
-        </Row>
-
-        <p>sub-element align right</p>
-        <Row type="flex" justify="end">
-            <Col span={4}>col-4</Col>
-            <Col span={4}>col-4</Col>
-            <Col span={4}>col-4</Col>
-            <Col span={4}>col-4</Col>
-        </Row>
-
-        <p>sub-element monospaced arrangement</p>
-        <Row type="flex" justify="space-between">
-            <Col span={4}>col-4</Col>
-            <Col span={4}>col-4</Col>
-            <Col span={4}>col-4</Col>
-            <Col span={4}>col-4</Col>
-        </Row>
-
-        <p>sub-element align full</p>
-        <Row type="flex" justify="space-around">
-            <Col span={4}>col-4</Col>
-            <Col span={4}>col-4</Col>
-            <Col span={4}>col-4</Col>
-            <Col span={4}>col-4</Col>
-        </Row>
-    </div>
-));
+export default {
+  title: 'Grid'
+}
+
+export const GridDefault = () => (
+  <div>
+    <Row>
+      <Col span={24}>col-24</Col>
+    </Row>
+    <Row>
+      <Col span={12}>col-12</Col>
+      <Col span={12}>col-12</Col>
+    </Row>
+    <Row>
+      <Col span={8}>col-8</Col>
+      <Col span={8}>col-8</Col>
+      <Col span={8}>col-8</Col>
+    </Row>
+    <Row>
+      <Col span={6}>col-6</Col>
+      <Col span={6}>col-6</Col>
+      <Col span={6}>col-6</Col>
+      <Col span={6}>col-6</Col>
+    </Row>
+  </div>
+);
+
+
+export const GridWithGutter = () => (
+  <div className="gutter-example">
+    <p>横向间距16</p>
+    <hr />
+    <Row gutter={16}>
+      <Col className="gutter-row" span={6}>
+        <div className="gutter-box">col-6</div>
+      </Col>
+      <Col className="gutter-row" span={6}>
+        <div className="gutter-box">col-6</div>
+      </Col>
+      <Col className="gutter-row" span={6}>
+        <div className="gutter-box">col-6</div>
+      </Col>
+      <Col className="gutter-row" span={6}>
+        <div className="gutter-box">col-6</div>
+      </Col>
+    </Row>
+    <p>横向间距16,纵向间距48</p>
+    <hr />
+    <Row gutter={[16, 48]}>
+      <Col className="gutter-row" span={6}>
+        <div className="gutter-box">col-6</div>
+      </Col>
+      <Col className="gutter-row" span={6}>
+        <div className="gutter-box">col-6</div>
+      </Col>
+      <Col className="gutter-row" span={6}>
+        <div className="gutter-box">col-6</div>
+      </Col>
+      <Col className="gutter-row" span={6}>
+        <div className="gutter-box">col-6</div>
+      </Col>
+      <Col className="gutter-row" span={6}>
+        <div className="gutter-box">col-6</div>
+      </Col>
+      <Col className="gutter-row" span={6}>
+        <div className="gutter-box">col-6</div>
+      </Col>
+      <Col className="gutter-row" span={6}>
+        <div className="gutter-box">col-6</div>
+      </Col>
+      <Col className="gutter-row" span={6}>
+        <div className="gutter-box">col-6</div>
+      </Col>
+    </Row>
+    <p>横向间距16,纵向间距24</p>
+    <hr />
+    <Row gutter={[16, 24]}>
+      <Col className="gutter-row" span={6}>
+        <div className="gutter-box">col-6</div>
+      </Col>
+      <Col className="gutter-row" span={6}>
+        <div className="gutter-box">col-6</div>
+      </Col>
+      <Col className="gutter-row" span={6}>
+        <div className="gutter-box">col-6</div>
+      </Col>
+      <Col className="gutter-row" span={6}>
+        <div className="gutter-box">col-6</div>
+      </Col>
+      <Col className="gutter-row" span={6}>
+        <div className="gutter-box">col-6</div>
+      </Col>
+      <Col className="gutter-row" span={6}>
+        <div className="gutter-box">col-6</div>
+      </Col>
+      <Col className="gutter-row" span={6}>
+        <div className="gutter-box">col-6</div>
+      </Col>
+      <Col className="gutter-row" span={6}>
+        <div className="gutter-box">col-6</div>
+      </Col>
+    </Row>
+  </div>
+);
+
+export const GridWithOffset = () => (
+  <div>
+    <Row>
+      <Col span={8}>col-8</Col>
+      <Col span={8} offset={8}>
+        col-8
+      </Col>
+    </Row>
+    <Row>
+      <Col span={6} offset={6}>
+        col-6 col-offset-6
+      </Col>
+      <Col span={6} offset={6}>
+        col-6 col-offset-6
+      </Col>
+    </Row>
+    <Row>
+      <Col span={12} offset={6}>
+        col-12 col-offset-6
+      </Col>
+    </Row>
+  </div>
+);
+
+export const GridWithPullPush = () => (
+  <div>
+    <Row>
+      <Col span={18} push={6}>
+        col-18 col-push-6
+      </Col>
+      <Col span={6} pull={18}>
+        col-6 col-pull-18
+      </Col>
+    </Row>
+  </div>
+);
+
+export const GridWithTypeFlex = () => (
+  <div>
+    <p>sub-element align left</p>
+    <Row type="flex" justify="start">
+      <Col span={4}>col-4</Col>
+      <Col span={4}>col-4</Col>
+      <Col span={4}>col-4</Col>
+      <Col span={4}>col-4</Col>
+    </Row>
+
+    <p>sub-element align center</p>
+    <Row type="flex" justify="center">
+      <Col span={4}>col-4</Col>
+      <Col span={4}>col-4</Col>
+      <Col span={4}>col-4</Col>
+      <Col span={4}>col-4</Col>
+    </Row>
+
+    <p>sub-element align right</p>
+    <Row type="flex" justify="end">
+      <Col span={4}>col-4</Col>
+      <Col span={4}>col-4</Col>
+      <Col span={4}>col-4</Col>
+      <Col span={4}>col-4</Col>
+    </Row>
+
+    <p>sub-element monospaced arrangement</p>
+    <Row type="flex" justify="space-between">
+      <Col span={4}>col-4</Col>
+      <Col span={4}>col-4</Col>
+      <Col span={4}>col-4</Col>
+      <Col span={4}>col-4</Col>
+    </Row>
+
+    <p>sub-element align full</p>
+    <Row type="flex" justify="space-around">
+      <Col span={4}>col-4</Col>
+      <Col span={4}>col-4</Col>
+      <Col span={4}>col-4</Col>
+      <Col span={4}>col-4</Col>
+    </Row>
+  </div>
+);
+
 const DemoBox = props => <p className={`height-${props.value}`}>{props.children}</p>;
 
-stories.add('grid with flex 子元素垂直对齐', () => (
-    <div className="demo5">
-        <p>Align Top</p>
-        <Row type="flex" justify="center" align="top">
-            <Col span={4}><DemoBox value={100}>col-4</DemoBox></Col>
-            <Col span={4}><DemoBox value={50}>col-4</DemoBox></Col>
-            <Col span={4}><DemoBox value={120}>col-4</DemoBox></Col>
-            <Col span={4}><DemoBox value={80}>col-4</DemoBox></Col>
-        </Row>
-
-        <p>Align Center</p>
-        <Row type="flex" justify="space-around" align="middle">
-            <Col span={4}><DemoBox value={100}>col-4</DemoBox></Col>
-            <Col span={4}><DemoBox value={50}>col-4</DemoBox></Col>
-            <Col span={4}><DemoBox value={120}>col-4</DemoBox></Col>
-            <Col span={4}><DemoBox value={80}>col-4</DemoBox></Col>
-        </Row>
-
-        <p>Align Bottom</p>
-        <Row type="flex" justify="space-between" align="bottom">
-            <Col span={4}><DemoBox value={100}>col-4</DemoBox></Col>
-            <Col span={4}><DemoBox value={50}>col-4</DemoBox></Col>
-            <Col span={4}><DemoBox value={120}>col-4</DemoBox></Col>
-            <Col span={4}><DemoBox value={80}>col-4</DemoBox></Col>
-        </Row>
-    </div>
-));
-stories.add('grid with flex & order', () => (
-    <div>
-        <Row type="flex">
-            <Col span={6} order={4}>1 col-order-4</Col>
-            <Col span={6} order={3}>2 col-order-3</Col>
-            <Col span={6} order={2}>3 col-order-2</Col>
-            <Col span={6} order={1}>4 col-order-1</Col>
-        </Row>
-    </div>
-));
-stories.add('grid bootstrap 响应式', () => (
-    <div>
-        <Row>
-            <Col xs={2} sm={4} md={6} lg={8} xl={10}>Col</Col>
-            <Col xs={20} sm={16} md={12} lg={8} xl={4}>Col</Col>
-            <Col xs={2} sm={4} md={6} lg={8} xl={10}>Col</Col>
-        </Row>
-        <Row>
-            <Col xs={{ span: 5, offset: 1 }} lg={{ span: 6, offset: 2 }}>Col</Col>
-            <Col xs={{ span: 11, offset: 1 }} lg={{ span: 6, offset: 2 }}>Col</Col>
-            <Col xs={{ span: 5, offset: 1 }} lg={{ span: 6, offset: 2 }}>Col</Col>
-        </Row>
-    </div>
-));
+export const GridWithFlexChildVerticalAlign = () => (
+  <div className="demo5">
+    <p>Align Top</p>
+    <Row type="flex" justify="center" align="top">
+      <Col span={4}>
+        <DemoBox value={100}>col-4</DemoBox>
+      </Col>
+      <Col span={4}>
+        <DemoBox value={50}>col-4</DemoBox>
+      </Col>
+      <Col span={4}>
+        <DemoBox value={120}>col-4</DemoBox>
+      </Col>
+      <Col span={4}>
+        <DemoBox value={80}>col-4</DemoBox>
+      </Col>
+    </Row>
+
+    <p>Align Center</p>
+    <Row type="flex" justify="space-around" align="middle">
+      <Col span={4}>
+        <DemoBox value={100}>col-4</DemoBox>
+      </Col>
+      <Col span={4}>
+        <DemoBox value={50}>col-4</DemoBox>
+      </Col>
+      <Col span={4}>
+        <DemoBox value={120}>col-4</DemoBox>
+      </Col>
+      <Col span={4}>
+        <DemoBox value={80}>col-4</DemoBox>
+      </Col>
+    </Row>
+
+    <p>Align Bottom</p>
+    <Row type="flex" justify="space-between" align="bottom">
+      <Col span={4}>
+        <DemoBox value={100}>col-4</DemoBox>
+      </Col>
+      <Col span={4}>
+        <DemoBox value={50}>col-4</DemoBox>
+      </Col>
+      <Col span={4}>
+        <DemoBox value={120}>col-4</DemoBox>
+      </Col>
+      <Col span={4}>
+        <DemoBox value={80}>col-4</DemoBox>
+      </Col>
+    </Row>
+  </div>
+);
+
+export const GridWithFlexOrder = () => (
+  <div>
+    <Row type="flex">
+      <Col span={6} order={4}>
+        1 col-order-4
+      </Col>
+      <Col span={6} order={3}>
+        2 col-order-3
+      </Col>
+      <Col span={6} order={2}>
+        3 col-order-2
+      </Col>
+      <Col span={6} order={1}>
+        4 col-order-1
+      </Col>
+    </Row>
+  </div>
+);
+
+export const GridBootstrap = () => (
+  <div>
+    <Row>
+      <Col xs={2} sm={4} md={6} lg={8} xl={10}>
+        Col
+      </Col>
+      <Col xs={20} sm={16} md={12} lg={8} xl={4}>
+        Col
+      </Col>
+      <Col xs={2} sm={4} md={6} lg={8} xl={10}>
+        Col
+      </Col>
+    </Row>
+    <Row>
+      <Col xs={{ span: 5, offset: 1 }} lg={{ span: 6, offset: 2 }}>
+        Col
+      </Col>
+      <Col xs={{ span: 11, offset: 1 }} lg={{ span: 6, offset: 2 }}>
+        Col
+      </Col>
+      <Col xs={{ span: 5, offset: 1 }} lg={{ span: 6, offset: 2 }}>
+        Col
+      </Col>
+    </Row>
+  </div>
+);

+ 56 - 47
packages/semi-ui/icons/_story/icon.stories.js

@@ -1,54 +1,63 @@
 import React from 'react';
-import { storiesOf } from '@storybook/react'; // import { withKnobs, text, boolean } from '@storybook/addon-knobs';
 
 import Others from './Others';
-import { IconHome, IconLock, IconClear, IconTickCircle, IconTick, IconClose, IconCaretUp } from '@douyinfe/semi-icons';
-const stories = storiesOf('Icon', module); // stories.addDecorator(withKnobs);;
+import {
+  IconHome,
+  IconLock,
+  IconClear,
+  IconTickCircle,
+  IconTick,
+  IconClose,
+  IconCaretup,
+} from '@douyinfe/semi-icons';
 
-stories.add('Icon', () => (
+export default {
+  title: 'Icon'
+}
+
+export {
+  Others
+}
+
+export const IconDemo = () => (
+  <div>
     <div>
-        <div>
-            <IconHome size="large" />
-            <IconLock size="small" />
-            <IconLock />
-            <IconClear />
-            <IconTickCircle />
-            <IconTick />
-            <IconClose />
-            <IconCaretUp />
-        </div>
-        <div
-            style={{
-                color: 'red',
-            }}
-        >
-            <IconHome size="large" />
-            <IconLock size="small" />
-            <IconLock />
-            <IconClear />
-            <IconTickCircle />
-            <IconTick />
-            <IconClose />
-            <IconCaretUp />
-        </div>
-        <div
-            style={{
-                color: 'pink',
-            }}
-        >
-            <IconHome size="large" />
-            <IconLock size="small" />
-            <IconLock />
-            <IconClear />
-            <IconTickCircle />
-            <IconTick />
-            <IconClose />
-            <IconCaretUp />
-        </div>
+      <IconHome size="large" />
+      <IconLock size="small" />
+      <IconLock />
+      <IconClear />
+      <IconTickCircle />
+      <IconTick />
+      <IconClose />
+      <IconCaretup />
     </div>
-));
-stories.add('others', () => (
-    <div>
-        <Others />
+    <div
+      style={{
+        color: 'red',
+      }}
+    >
+      <IconHome size="large" />
+      <IconLock size="small" />
+      <IconLock />
+      <IconClear />
+      <IconTickCircle />
+      <IconTick />
+      <IconClose />
+      <IconCaretup />
+    </div>
+    <div
+      style={{
+        color: 'pink',
+      }}
+    >
+      <IconHome size="large" />
+      <IconLock size="small" />
+      <IconLock />
+      <IconClear />
+      <IconTickCircle />
+      <IconTick />
+      <IconClose />
+      <IconCaretup />
     </div>
-));
+  </div>
+);

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 677 - 507
packages/semi-ui/input/_story/input.stories.js


+ 625 - 539
packages/semi-ui/inputNumber/_story/inputNumber.stories.js

@@ -1,557 +1,643 @@
 import React, { useRef, useState } from 'react';
-import { storiesOf } from '@storybook/react';
 // import { withKnobs, text, boolean } from '@storybook/addon-knobs';
 import './inputNumber.scss';
 import InputNumber from '../index';
 import Button from '../../button/index';
 import { withField, Form } from '../../index';
 
-const stories = storiesOf('InputNumber', module);
-
-// stories.addDecorator(withKnobs);;
+export default {
+  title: 'InputNumber',
+}
 
 function log(v, e) {
-    const type = typeof v;
-    console.log(type, v);
+  const type = typeof v;
+  console.log(type, v);
 }
 
 const createOnChange = changeFn => {
-    return (...args) => {
-        log(...args);
-        if (typeof changeFn === 'function') {
-            changeFn(...args);
-        }
-    };
+  return (...args) => {
+    log(...args);
+    if (typeof changeFn === 'function') {
+      changeFn(...args);
+    }
+  };
 };
 
-stories.add('Input number', () => {
-    const Demo = () => {
-        const [controlledValue, setControlledValue] = useState(10.1);
-        const controlledOnChange = createOnChange(setControlledValue);
-
-        const [controlledValue2, setControlledValue2] = useState(9);
-        const controlledOnChange2 = createOnChange(setControlledValue2);
-
-        const [decimal, setDecimal] = useState(10.01);
-        const decimalOnChange = createOnChange(setDecimal);
-
-        const [formattedVal, setFormattedVal] = useState(10.02);
-        const formattedValOnChange = createOnChange(setFormattedVal);
-
-        const [formattedDecimal, setFormattedDecimal] = useState(10.03);
-        const formattedDecimalOnChange = createOnChange(setFormattedDecimal);
-
-        return (
-            <div className="inputNumber">
-                <label>简单数字输入框</label>
-                <InputNumber onChange={log} />
-                <br />
-
-                <label>限定上下界与整数步长</label>
-                <InputNumber max={10} min={0} step={1} />
-                <br />
-
-                <label>限定上下界与小数步长</label>
-                <InputNumber max={10} min={0} step={0.1} defaultValue={0.2} precision={2} />
-                <br />
-
-                <label>格式化</label>
-                <InputNumber
-                    defaultValue={1000}
-                    onChange={log}
-                    formatter={value => `$ ${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')}
-                    parser={value => value.replace(/\$\s?|(,*)/g, '')}
-                />
-                <br />
-
-                <label>小数</label>
-                <InputNumber defaultValue={10.08} precision={2} onChange={log} />
-                <br />
-
-                <label>格式化+小数</label>
-                <InputNumber
-                    defaultValue={1000}
-                    precision={2}
-                    onChange={log}
-                    formatter={value => `$ ${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')}
-                    parser={value => value.replace(/\$\s?|(,*)/g, '')}
-                />
-                <br />
-
-                <label>受控</label>
-                <InputNumber value={controlledValue} onChange={controlledOnChange} />
-                <br />
-
-                <label>受控+上下界</label>
-                <InputNumber min={1} max={10} value={controlledValue2} onChange={controlledOnChange2} />
-                <br />
-
-                <label>小数+受控</label>
-                <InputNumber value={decimal} precision={2} onChange={decimalOnChange} />
-                <br />
-
-                <label>格式化+受控</label>
-                <InputNumber
-                    defaultValue={1000}
-                    precision={0}
-                    formatter={value => `$ ${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')}
-                    parser={value => value.replace(/\$\s?|(,*)/g, '')}
-                    onChange={formattedValOnChange}
-                    value={formattedVal}
-                />
-                <br />
-
-                <label>格式化+小数+受控</label>
-                <InputNumber
-                    precision={2}
-                    formatter={value => `$ ${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')}
-                    parser={value => value.replace(/\$\s?|(,*)/g, '')}
-                    onChange={formattedDecimalOnChange}
-                    value={formattedDecimal}
-                />
-            </div>
-        );
-    };
+export const _InputNumber = () => {
+  const Demo = () => {
+    const [controlledValue, setControlledValue] = useState(10.1);
+    const controlledOnChange = createOnChange(setControlledValue);
+
+    const [controlledValue2, setControlledValue2] = useState(9);
+    const controlledOnChange2 = createOnChange(setControlledValue2);
+
+    const [decimal, setDecimal] = useState(10.01);
+    const decimalOnChange = createOnChange(setDecimal);
+
+    const [formattedVal, setFormattedVal] = useState(10.02);
+    const formattedValOnChange = createOnChange(setFormattedVal);
+
+    const [formattedDecimal, setFormattedDecimal] = useState(10.03);
+    const formattedDecimalOnChange = createOnChange(setFormattedDecimal);
+
+    return (
+      <div className="inputNumber">
+        <label>简单数字输入框</label>
+        <InputNumber onChange={log} />
+        <br />
+
+        <label>限定上下界与整数步长</label>
+        <InputNumber max={10} min={0} step={1} />
+        <br />
+
+        <label>限定上下界与小数步长</label>
+        <InputNumber max={10} min={0} step={0.1} defaultValue={0.2} precision={2} />
+        <br />
+
+        <label>格式化</label>
+        <InputNumber
+          defaultValue={1000}
+          onChange={log}
+          formatter={value => `$ ${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')}
+          parser={value => value.replace(/\$\s?|(,*)/g, '')}
+        />
+        <br />
+
+        <label>小数</label>
+        <InputNumber defaultValue={10.08} precision={2} onChange={log} />
+        <br />
+
+        <label>格式化+小数</label>
+        <InputNumber
+          defaultValue={1000}
+          precision={2}
+          onChange={log}
+          formatter={value => `$ ${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')}
+          parser={value => value.replace(/\$\s?|(,*)/g, '')}
+        />
+        <br />
+
+        <label>受控</label>
+        <InputNumber value={controlledValue} onChange={controlledOnChange} />
+        <br />
+
+        <label>受控+上下界</label>
+        <InputNumber min={1} max={10} value={controlledValue2} onChange={controlledOnChange2} />
+        <br />
+
+        <label>小数+受控</label>
+        <InputNumber value={decimal} precision={2} onChange={decimalOnChange} />
+        <br />
+
+        <label>格式化+受控</label>
+        <InputNumber
+          defaultValue={1000}
+          precision={0}
+          formatter={value => `$ ${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')}
+          parser={value => value.replace(/\$\s?|(,*)/g, '')}
+          onChange={formattedValOnChange}
+          value={formattedVal}
+        />
+        <br />
+
+        <label>格式化+小数+受控</label>
+        <InputNumber
+          precision={2}
+          formatter={value => `$ ${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')}
+          parser={value => value.replace(/\$\s?|(,*)/g, '')}
+          onChange={formattedDecimalOnChange}
+          value={formattedDecimal}
+        />
+      </div>
+    );
+  };
+
+  return <Demo />;
+};
 
-    return <Demo />;
-});
-
-stories.add('inputnumber use ref call focus', () => {
-    const Demo = () => {
-        const ref = useRef();
-        const focus = () => {
-            ref.current && ref.current.focus();
-        };
-        const blur = () => ref.current && ref.current.blur();
-
-        return (
-            <>
-                <InputNumber ref={ref} />
-                <Button onClick={focus}>focus</Button>
-                <Button onClick={blur}>blur</Button>
-            </>
-        );
-    };
-    return <Demo />;
-});
-
-stories.add('uncontrolled InputNumber', () => {
-    const Demo = function Demo(props = {}) {
-        return (
-            <div style={{ width: 450, padding: 20 }}>
-                <h5>defaultValue</h5>
-                <InputNumber defaultValue={1020} onChange={log} />
-                <br />
-
-                <h5>defaultValue + formatter + parser</h5>
-                <InputNumber
-                    defaultValue={1020}
-                    onChange={log}
-                    formatter={value => `$ ${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')}
-                    parser={value => value.replace(/\$\s?|(,*)/g, '')}
-                />
-                <br />
-
-                <h5>defaultValue + precision + formatter + parser</h5>
-                <InputNumber
-                    defaultValue={1020}
-                    precision={2}
-                    onChange={log}
-                    formatter={value => `$ ${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')}
-                    parser={value => value.replace(/\$\s?|(,*)/g, '')}
-                />
-                <br />
-
-                <h5>defaultValue + precision + max + min + formatter + parser</h5>
-                <InputNumber
-                    defaultValue={1020}
-                    precision={2}
-                    onChange={log}
-                    max={1000}
-                    min={500}
-                    formatter={value => `$ ${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')}
-                    parser={value => value.replace(/\$\s?|(,*)/g, '')}
-                />
-                <br />
-            </div>
-        );
-    };
+_InputNumber.story = {
+  name: 'Input number',
+};
 
-    return <Demo />;
-});
-
-stories.add('controlled InputNumber', () => {
-    const ControlledDemo = function ControlledDemo(props = {}) {
-        const [value, setValue] = useState(0);
-        const _setValue = createOnChange(setValue);
-
-        const [value1, setValue1] = useState(0.234);
-        const _setValue1 = createOnChange(setValue1);
-
-        const [value2, setValue2] = useState(1000);
-        const _setValue2 = createOnChange(setValue2);
-
-        const [value3, setValue3] = useState(0.21);
-        const _setValue3 = createOnChange(setValue3);
-
-        const [value4, setValue4] = useState(3);
-        const randomSetValue4 = createOnChange(v => {
-            setValue4(Math.random() * 3 + 1);
-        });
-
-        const [value5, setValue5] = useState(5);
-        const randomSetValue5 = createOnChange(v => {
-            setValue5(Math.random() * 5 + 1);
-        });
-
-        const [value6, setValue6] = useState(6);
-        const randomSetValue6 = createOnChange(v => {
-            const num = Math.random() * 10 + 9;
-            console.log('random set: ', num);
-            setValue6(num);
-        });
-        const _setValue6 = createOnChange(setValue6);
-
-        return (
-            <div style={{ width: 450, padding: 20 }}>
-                <h5>defaultValue</h5>
-                <InputNumber defaultValue={1020} onChange={log} />
-                <br />
-                <h5>value</h5>
-                <InputNumber value={1000} onChange={log} />
-                <br />
-                <h5>value + onChange</h5>
-                <InputNumber value={value} onChange={_setValue} onBlur={() => console.log('blur')} />
-                <br />
-                <h5>value + precision + onChange</h5>
-                <InputNumber value={value1} onChange={_setValue1} precision={2} />
-                <br />
-                <h5>value + step + precision + onChange</h5>
-                <InputNumber step={0.2} value={value3} onChange={_setValue3} precision={2} />
-                <br />
-
-                <h5>value + precision + onChange + formatter + parser</h5>
-                <Button onClick={() => setValue2(undefined)}>Empty</Button>
-                <InputNumber
-                    value={value2}
-                    precision={2}
-                    onChange={_setValue2}
-                    formatter={value => `$ ${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')}
-                    parser={value => value.replace(/\$\s?|(,*)/g, '')}
-                />
-                <br />
-
-                <h5>random set value + precision</h5>
-                <Button onClick={randomSetValue4}>Random Set Value</Button>
-                <InputNumber value={value4} precision={2} onChange={log} />
-                <br />
-
-                <h5>random set value + precision + formatter + parser</h5>
-                <Button onClick={randomSetValue5}>Random Set Value</Button>
-                <Button onClick={() => setValue5(undefined)}>Empty</Button>
-                <InputNumber
-                    value={value5}
-                    precision={2}
-                    onChange={log}
-                    formatter={value => `$ ${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')}
-                    parser={value => value.replace(/\$\s?|(,*)/g, '')}
-                />
-                <br />
-
-                <h5>random set value + max + min + precision + onChange</h5>
-                <Button onClick={randomSetValue6}>Random Set Value</Button>
-                <Button onClick={() => setValue6(undefined)}>Empty</Button>
-                <InputNumber max={18} min={-8} value={value6} precision={2} onChange={_setValue6} />
-                <br />
-            </div>
-        );
+export const InputnumberUseRefCallFocus = () => {
+  const Demo = () => {
+    const ref = useRef();
+    const focus = () => {
+      ref.current && ref.current.focus();
     };
+    const blur = () => ref.current && ref.current.blur();
+
+    return (
+      <>
+        <InputNumber ref={ref} />
+        <Button onClick={focus}>focus</Button>
+        <Button onClick={blur}>blur</Button>
+      </>
+    );
+  };
+  return <Demo />;
+};
 
-    return <ControlledDemo />;
-});
-
-stories.add('innnerButtons', () => {
-    const Demo = () => {
-        return (
-            <div style={{ width: 450 }}>
-                <label>innerButtons=false</label>
-                <div>
-                    <InputNumber innerButtons={false} />
-                </div>
-                <br />
-                <label>innerButtons=true</label>
-                <div>
-                    <InputNumber innerButtons={true} suffix={'小时'} min={0} />
-                </div>
-            </div>
-        );
-    };
-    return <Demo />;
-});
-
-stories.add('shiftStep', () => {
-    const Demo = () => {
-        return (
-            <div style={{ width: 450 }}>
-                <label>shiftStep=100,可长按</label>
-                <div>
-                    <InputNumber shiftStep={100} />
-                </div>
-            </div>
-        );
-    };
-    return <Demo />;
-});
-
-stories.add('onChange无限触发问题', () => {
-    const Demo = () => {
-        const [disabled, setDisabled] = useState(true);
-        const [disabled2, setDisabled2] = useState(false);
-        const [val, setVal] = useState(2);
-
-        return (
-            <>
-                <h3>数值没有持续变化说明正常,v1.10.0修复</h3><br/><br/>
-                <div>点击2后点击输入框,然后点击按钮会触发</div>
-                {
-                    disabled ? (
-                    <div onClick={() => { setDisabled(false); }}>
-                        {val}
-                    </div>) :
-                    <InputNumber style={{width: 120}} val={val} innerButtons onChange={res => setVal(res)} />
-                }
-                <br/><br/>
-                <div>点击按钮后切换 disabled 状态</div>
-                <div>disablde: {String(disabled2)}</div>
-                <div>
-                    <InputNumber 
-                        defaultValue={12} 
-                        innerButtons 
-                        disabled={disabled2} 
-                        onChange={() => setDisabled2(true)} 
-                    />
-                </div>
-            </>
-        );
-    };
-    return <Demo />;
-});
-
-stories.add('clear icon 位置', () => {
-    const Demo = () => {
-        return (
-            <InputNumber 
-                autoFocus
-                defaultValue={12} 
-                innerButtons
-                showClear
-            />
-        );
-    };
-    return <Demo />;
-});
-
-stories.add('uncontrolled keepFocus', () => {
-    const Demo = () => {
-        const [val, setVal] = useState(2);
-        const [val2, setVal2] = useState(2);
-
-        return (
-            <div style={{ width: 450, padding: 20 }}>
-                <h5>defaultValue</h5>
-                <InputNumber defaultValue={1020} onChange={log} keepFocus={true} />
-                <br />
-                <h5>defaultValue + formatter + parser</h5>
-                <InputNumber
-                    keepFocus={true}
-                    defaultValue={1020}
-                    onChange={log}
-                    formatter={value => `$ ${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')}
-                    parser={value => value.replace(/\$\s?|(,*)/g, '')}
-                />
-                <br />
-                <h5>defaultValue + precision + formatter + parser</h5>
-                <InputNumber
-                    keepFocus={true}
-                    defaultValue={1020}
-                    precision={2}
-                    onChange={log}
-                    formatter={value => `$ ${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')}
-                    parser={value => value.replace(/\$\s?|(,*)/g, '')}
-                />
-                <br />
-                <h5>defaultValue + precision + max + min + formatter + parser</h5>
-                <InputNumber
-                    keepFocus={true}
-                    defaultValue={1020}
-                    precision={2}
-                    onChange={log}
-                    max={1000}
-                    min={500}
-                    formatter={value => `$ ${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')}
-                    parser={value => value.replace(/\$\s?|(,*)/g, '')}
-                />
-                <br />
-            </div>
-        );
-    };
-    return <Demo />;
-});
-
-stories.add('controlled keepFocus', () => {
-    const Demo = () => {
-        const [value, setValue] = useState(0);
-        const _setValue = createOnChange(setValue);
-
-        const [value1, setValue1] = useState(0.234);
-        const _setValue1 = createOnChange(setValue1);
-
-        const [value2, setValue2] = useState(1000);
-        const _setValue2 = createOnChange(setValue2);
-
-        const [value3, setValue3] = useState(0.21);
-        const _setValue3 = createOnChange(setValue3);
-
-        const [value4, setValue4] = useState(3);
-        const randomSetValue4 = createOnChange(v => {
-            setValue4(Math.random() * 3 + 1);
-        });
-
-        const [value5, setValue5] = useState(5);
-        const randomSetValue5 = createOnChange(v => {
-            setValue5(Math.random() * 5 + 1);
-        });
-
-        const [value6, setValue6] = useState(6);
-        const randomSetValue6 = createOnChange(v => {
-            const num = Math.random() * 10 + 9;
-            console.log('random set: ', num);
-            setValue6(num);
-        });
-        const _setValue6 = createOnChange(setValue6);
-
-        return (
-            <div style={{ width: 450, padding: 20 }}>
-                <h5>defaultValue</h5>
-                <InputNumber keepFocus={true} defaultValue={1020} onChange={log} />
-                <br />
-                <h5>value</h5>
-                <InputNumber keepFocus={true} value={1000} onChange={log} />
-                <br />
-                <h5>value + onChange</h5>
-                <InputNumber keepFocus={true} value={value} onChange={_setValue} onBlur={() => console.log('blur')} />
-                <br />
-                <h5>value + precision + onChange</h5>
-                <InputNumber keepFocus={true} value={value1} onChange={_setValue1} precision={2} />
-                <br />
-                <h5>value + step + precision + onChange</h5>
-                <InputNumber keepFocus={true} step={0.2} value={value3} onChange={_setValue3} precision={2} />
-                <br />
-
-                <h5>value + precision + onChange + formatter + parser</h5>
-                <Button onClick={() => setValue2(undefined)}>Empty</Button>
-                <InputNumber
-                    keepFocus={true}
-                    value={value2}
-                    precision={2}
-                    onChange={_setValue2}
-                    formatter={value => `$ ${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')}
-                    parser={value => value.replace(/\$\s?|(,*)/g, '')}
-                />
-                <br />
-
-                <h5>random set value + precision</h5>
-                <Button onClick={randomSetValue4}>Random Set Value</Button>
-                <InputNumber keepFocus={true} value={value4} precision={2} onChange={log} />
-                <br />
-
-                <h5>random set value + precision + formatter + parser</h5>
-                <Button onClick={randomSetValue5}>Random Set Value</Button>
-                <Button onClick={() => setValue5(undefined)}>Empty</Button>
-                <InputNumber
-                    keepFocus={true}
-                    value={value5}
-                    precision={2}
-                    onChange={log}
-                    formatter={value => `$ ${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')}
-                    parser={value => value.replace(/\$\s?|(,*)/g, '')}
-                />
-                <br />
-
-                <h5>random set value + max + min + precision + onChange</h5>
-                <Button onClick={randomSetValue6}>Random Set Value</Button>
-                <Button onClick={() => setValue6(undefined)}>Empty</Button>
-                <InputNumber keepFocus={true} max={18} min={-8} value={value6} precision={2} onChange={_setValue6} />
-                <br />
-            </div>
-        )
-    };
-    return <Demo />;
-});
-
-stories.add('disabled style', () => {
-    const Demo = () => {
-        return (
-            <>
-                <label>prop disabled</label>
-                <InputNumber disabled /><br /><br />
-                <label>max limit</label>
-                <InputNumber min={1} max={10} defaultValue={10} /><br /><br />
-                <label>min limit</label>
-                <InputNumber min={1} max={10} defaultValue={1} /><br /><br />
-            </>
-        );
-    }
-});
-
-stories.add('Form.CustomInput', () => {
-    const Demo = () => {
-        const CustomInput = withField(InputNumber, { onKeyChangeFnName: 'onNumberChange' });
-
-        return (
-            <>
-                <h4>not controlled + without formatter</h4>
-                <InputNumber 
-                    onChange={(...args) => console.log('inputNumber change', ...args)}
-                    onNumberChange={(...args) => console.log('inputNumber number change', ...args)}
-                />
-                <h4>not controlled + formatter(onChange会包括英文字符,onNumberChange不包括)</h4>
-                <InputNumber 
-                    formatter={value => `${value}`.replace(/\D/g, '')}
-                    onChange={(...args) => console.log('inputNumber change', ...args)}
-                    onNumberChange={(...args) => console.log('inputNumber number change', ...args)}
-                />
-                <Form onValueChange={(v)=>console.log(v)}>
-                    <h4>Form + Form.InputNumber + formatter + onChange(onChange包括英文字符,显示没有英文字符)</h4>
-                    <Form.InputNumber 
-                        field='formOriginalInputNumber' 
-                        noLabel
-                        formatter={value => `${value}`.replace(/\D/g, '')}
-                        onChange={(...args) => console.log('form inputNumber change', ...args)}
-                    />
-                    <h4>Form + withField InputNumber + formatter + onNumberChange(onNumberChange不包括英文字符,显示也不包括英文字符)</h4>
-                    <CustomInput
-                        field='formCustomInputNumber' 
-                        noLabel
-                        formatter={value => `${value}`.replace(/\D/g, '')}
-                    />
-                </Form>
-                <h4>type=number (TODO:需要关注内置的按钮+不同浏览器对type=number的支持情况,比如 safari 貌似就不支持)</h4>
-                <InputNumber
-                    type="number"
-                    onChange={(...args) => console.log('inputNumber change', ...args)}
-                    onNumberChange={(...args) => console.log('inputNumber number change', ...args)}
-                />
-                <h4>测试 formatter + parser 是否正常</h4>
-                <InputNumber
-                    onChange={(v) => console.log(`Changed to: [${typeof v}] ${v}`)}
-                    defaultValue={1000}
-                    min={0}
-                    formatter={value => `¥ ${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')}
-                    parser={value => value.replace(/\¥\s?|(,*)/g, '')}
-                />
-            </>
-        );
-    };
-    return <Demo />;
-});
+InputnumberUseRefCallFocus.story = {
+  name: 'inputnumber use ref call focus',
+};
+
+export const UncontrolledInputNumber = () => {
+  const Demo = function Demo(props = {}) {
+    return (
+      <div style={{ width: 450, padding: 20 }}>
+        <h5>defaultValue</h5>
+        <InputNumber defaultValue={1020} onChange={log} />
+        <br />
+
+        <h5>defaultValue + formatter + parser</h5>
+        <InputNumber
+          defaultValue={1020}
+          onChange={log}
+          formatter={value => `$ ${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')}
+          parser={value => value.replace(/\$\s?|(,*)/g, '')}
+        />
+        <br />
+
+        <h5>defaultValue + precision + formatter + parser</h5>
+        <InputNumber
+          defaultValue={1020}
+          precision={2}
+          onChange={log}
+          formatter={value => `$ ${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')}
+          parser={value => value.replace(/\$\s?|(,*)/g, '')}
+        />
+        <br />
+
+        <h5>defaultValue + precision + max + min + formatter + parser</h5>
+        <InputNumber
+          defaultValue={1020}
+          precision={2}
+          onChange={log}
+          max={1000}
+          min={500}
+          formatter={value => `$ ${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')}
+          parser={value => value.replace(/\$\s?|(,*)/g, '')}
+        />
+        <br />
+      </div>
+    );
+  };
+
+  return <Demo />;
+};
+
+UncontrolledInputNumber.story = {
+  name: 'uncontrolled InputNumber',
+};
+
+export const ControlledInputNumber = () => {
+  const ControlledDemo = function ControlledDemo(props = {}) {
+    const [value, setValue] = useState(0);
+    const _setValue = createOnChange(setValue);
+
+    const [value1, setValue1] = useState(0.234);
+    const _setValue1 = createOnChange(setValue1);
+
+    const [value2, setValue2] = useState(1000);
+    const _setValue2 = createOnChange(setValue2);
+
+    const [value3, setValue3] = useState(0.21);
+    const _setValue3 = createOnChange(setValue3);
+
+    const [value4, setValue4] = useState(3);
+    const randomSetValue4 = createOnChange(v => {
+      setValue4(Math.random() * 3 + 1);
+    });
+
+    const [value5, setValue5] = useState(5);
+    const randomSetValue5 = createOnChange(v => {
+      setValue5(Math.random() * 5 + 1);
+    });
+
+    const [value6, setValue6] = useState(6);
+    const randomSetValue6 = createOnChange(v => {
+      const num = Math.random() * 10 + 9;
+      console.log('random set: ', num);
+      setValue6(num);
+    });
+    const _setValue6 = createOnChange(setValue6);
+
+    return (
+      <div style={{ width: 450, padding: 20 }}>
+        <h5>defaultValue</h5>
+        <InputNumber defaultValue={1020} onChange={log} />
+        <br />
+        <h5>value</h5>
+        <InputNumber value={1000} onChange={log} />
+        <br />
+        <h5>value + onChange</h5>
+        <InputNumber value={value} onChange={_setValue} onBlur={() => console.log('blur')} />
+        <br />
+        <h5>value + precision + onChange</h5>
+        <InputNumber value={value1} onChange={_setValue1} precision={2} />
+        <br />
+        <h5>value + step + precision + onChange</h5>
+        <InputNumber step={0.2} value={value3} onChange={_setValue3} precision={2} />
+        <br />
+
+        <h5>value + precision + onChange + formatter + parser</h5>
+        <Button onClick={() => setValue2(undefined)}>Empty</Button>
+        <InputNumber
+          value={value2}
+          precision={2}
+          onChange={_setValue2}
+          formatter={value => `$ ${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')}
+          parser={value => value.replace(/\$\s?|(,*)/g, '')}
+        />
+        <br />
+
+        <h5>random set value + precision</h5>
+        <Button onClick={randomSetValue4}>Random Set Value</Button>
+        <InputNumber value={value4} precision={2} onChange={log} />
+        <br />
+
+        <h5>random set value + precision + formatter + parser</h5>
+        <Button onClick={randomSetValue5}>Random Set Value</Button>
+        <Button onClick={() => setValue5(undefined)}>Empty</Button>
+        <InputNumber
+          value={value5}
+          precision={2}
+          onChange={log}
+          formatter={value => `$ ${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')}
+          parser={value => value.replace(/\$\s?|(,*)/g, '')}
+        />
+        <br />
+
+        <h5>random set value + max + min + precision + onChange</h5>
+        <Button onClick={randomSetValue6}>Random Set Value</Button>
+        <Button onClick={() => setValue6(undefined)}>Empty</Button>
+        <InputNumber max={18} min={-8} value={value6} precision={2} onChange={_setValue6} />
+        <br />
+      </div>
+    );
+  };
+
+  return <ControlledDemo />;
+};
+
+ControlledInputNumber.story = {
+  name: 'controlled InputNumber',
+};
+
+export const InnnerButtons = () => {
+  const Demo = () => {
+    return (
+      <div style={{ width: 450 }}>
+        <label>innerButtons=false</label>
+        <div>
+          <InputNumber innerButtons={false} />
+        </div>
+        <br />
+        <label>innerButtons=true</label>
+        <div>
+          <InputNumber innerButtons={true} suffix={'小时'} min={0} />
+        </div>
+      </div>
+    );
+  };
+  return <Demo />;
+};
+
+InnnerButtons.story = {
+  name: 'innnerButtons',
+};
+
+export const ShiftStep = () => {
+  const Demo = () => {
+    return (
+      <div style={{ width: 450 }}>
+        <label>shiftStep=100,可长按</label>
+        <div>
+          <InputNumber shiftStep={100} />
+        </div>
+      </div>
+    );
+  };
+  return <Demo />;
+};
+
+ShiftStep.story = {
+  name: 'shiftStep',
+};
+
+export const OnChangeLimit = () => {
+  const Demo = () => {
+    const [disabled, setDisabled] = useState(true);
+    const [disabled2, setDisabled2] = useState(false);
+    const [val, setVal] = useState(2);
+
+    return (
+      <>
+        <h3>数值没有持续变化说明正常,v1.10.0修复</h3>
+        <br />
+        <br />
+        <div>点击2后点击输入框,然后点击按钮会触发</div>
+        {disabled ? (
+          <div
+            onClick={() => {
+              setDisabled(false);
+            }}
+          >
+            {val}
+          </div>
+        ) : (
+          <InputNumber
+            style={{ width: 120 }}
+            val={val}
+            innerButtons
+            onChange={res => setVal(res)}
+          />
+        )}
+        <br />
+        <br />
+        <div>点击按钮后切换 disabled 状态</div>
+        <div>disablde: {String(disabled2)}</div>
+        <div>
+          <InputNumber
+            defaultValue={12}
+            innerButtons
+            disabled={disabled2}
+            onChange={() => setDisabled2(true)}
+          />
+        </div>
+      </>
+    );
+  };
+  return <Demo />;
+};
+
+OnChangeLimit.story = {
+  name: 'onChange无限触发问题',
+};
+
+export const ClearIconPosition = () => {
+  const Demo = () => {
+    return <InputNumber autoFocus defaultValue={12} innerButtons showClear />;
+  };
+  return <Demo />;
+};
+
+ClearIconPosition.story = {
+  name: 'clear icon 位置',
+};
+
+export const UncontrolledKeepFocus = () => {
+  const Demo = () => {
+    const [val, setVal] = useState(2);
+    const [val2, setVal2] = useState(2);
+
+    return (
+      <div style={{ width: 450, padding: 20 }}>
+        <h5>defaultValue</h5>
+        <InputNumber defaultValue={1020} onChange={log} keepFocus={true} />
+        <br />
+        <h5>defaultValue + formatter + parser</h5>
+        <InputNumber
+          keepFocus={true}
+          defaultValue={1020}
+          onChange={log}
+          formatter={value => `$ ${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')}
+          parser={value => value.replace(/\$\s?|(,*)/g, '')}
+        />
+        <br />
+        <h5>defaultValue + precision + formatter + parser</h5>
+        <InputNumber
+          keepFocus={true}
+          defaultValue={1020}
+          precision={2}
+          onChange={log}
+          formatter={value => `$ ${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')}
+          parser={value => value.replace(/\$\s?|(,*)/g, '')}
+        />
+        <br />
+        <h5>defaultValue + precision + max + min + formatter + parser</h5>
+        <InputNumber
+          keepFocus={true}
+          defaultValue={1020}
+          precision={2}
+          onChange={log}
+          max={1000}
+          min={500}
+          formatter={value => `$ ${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')}
+          parser={value => value.replace(/\$\s?|(,*)/g, '')}
+        />
+        <br />
+      </div>
+    );
+  };
+  return <Demo />;
+};
+
+UncontrolledKeepFocus.story = {
+  name: 'uncontrolled keepFocus',
+};
+
+export const ControlledKeepFocus = () => {
+  const Demo = () => {
+    const [value, setValue] = useState(0);
+    const _setValue = createOnChange(setValue);
+
+    const [value1, setValue1] = useState(0.234);
+    const _setValue1 = createOnChange(setValue1);
+
+    const [value2, setValue2] = useState(1000);
+    const _setValue2 = createOnChange(setValue2);
+
+    const [value3, setValue3] = useState(0.21);
+    const _setValue3 = createOnChange(setValue3);
+
+    const [value4, setValue4] = useState(3);
+    const randomSetValue4 = createOnChange(v => {
+      setValue4(Math.random() * 3 + 1);
+    });
+
+    const [value5, setValue5] = useState(5);
+    const randomSetValue5 = createOnChange(v => {
+      setValue5(Math.random() * 5 + 1);
+    });
+
+    const [value6, setValue6] = useState(6);
+    const randomSetValue6 = createOnChange(v => {
+      const num = Math.random() * 10 + 9;
+      console.log('random set: ', num);
+      setValue6(num);
+    });
+    const _setValue6 = createOnChange(setValue6);
+
+    return (
+      <div style={{ width: 450, padding: 20 }}>
+        <h5>defaultValue</h5>
+        <InputNumber keepFocus={true} defaultValue={1020} onChange={log} />
+        <br />
+        <h5>value</h5>
+        <InputNumber keepFocus={true} value={1000} onChange={log} />
+        <br />
+        <h5>value + onChange</h5>
+        <InputNumber
+          keepFocus={true}
+          value={value}
+          onChange={_setValue}
+          onBlur={() => console.log('blur')}
+        />
+        <br />
+        <h5>value + precision + onChange</h5>
+        <InputNumber keepFocus={true} value={value1} onChange={_setValue1} precision={2} />
+        <br />
+        <h5>value + step + precision + onChange</h5>
+        <InputNumber
+          keepFocus={true}
+          step={0.2}
+          value={value3}
+          onChange={_setValue3}
+          precision={2}
+        />
+        <br />
+
+        <h5>value + precision + onChange + formatter + parser</h5>
+        <Button onClick={() => setValue2(undefined)}>Empty</Button>
+        <InputNumber
+          keepFocus={true}
+          value={value2}
+          precision={2}
+          onChange={_setValue2}
+          formatter={value => `$ ${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')}
+          parser={value => value.replace(/\$\s?|(,*)/g, '')}
+        />
+        <br />
+
+        <h5>random set value + precision</h5>
+        <Button onClick={randomSetValue4}>Random Set Value</Button>
+        <InputNumber keepFocus={true} value={value4} precision={2} onChange={log} />
+        <br />
+
+        <h5>random set value + precision + formatter + parser</h5>
+        <Button onClick={randomSetValue5}>Random Set Value</Button>
+        <Button onClick={() => setValue5(undefined)}>Empty</Button>
+        <InputNumber
+          keepFocus={true}
+          value={value5}
+          precision={2}
+          onChange={log}
+          formatter={value => `$ ${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')}
+          parser={value => value.replace(/\$\s?|(,*)/g, '')}
+        />
+        <br />
+
+        <h5>random set value + max + min + precision + onChange</h5>
+        <Button onClick={randomSetValue6}>Random Set Value</Button>
+        <Button onClick={() => setValue6(undefined)}>Empty</Button>
+        <InputNumber
+          keepFocus={true}
+          max={18}
+          min={-8}
+          value={value6}
+          precision={2}
+          onChange={_setValue6}
+        />
+        <br />
+      </div>
+    );
+  };
+  return <Demo />;
+};
+
+ControlledKeepFocus.story = {
+  name: 'controlled keepFocus',
+};
+
+export const DisabledStyle = () => {
+  const Demo = () => {
+    return (
+      <>
+        <label>prop disabled</label>
+        <InputNumber disabled />
+        <br />
+        <br />
+        <label>max limit</label>
+        <InputNumber min={1} max={10} defaultValue={10} />
+        <br />
+        <br />
+        <label>min limit</label>
+        <InputNumber min={1} max={10} defaultValue={1} />
+        <br />
+        <br />
+      </>
+    );
+  };
+
+  return <Demo />;
+};
+
+DisabledStyle.story = {
+  name: 'disabled style',
+};
+
+export const FormCustomInput = () => {
+  const Demo = () => {
+    const CustomInput = withField(InputNumber, { onKeyChangeFnName: 'onNumberChange' });
+
+    return (
+      <>
+        <h4>not controlled + without formatter</h4>
+        <InputNumber
+          onChange={(...args) => console.log('inputNumber change', ...args)}
+          onNumberChange={(...args) => console.log('inputNumber number change', ...args)}
+        />
+        <h4>not controlled + formatter(onChange会包括英文字符,onNumberChange不包括)</h4>
+        <InputNumber
+          formatter={value => `${value}`.replace(/\D/g, '')}
+          onChange={(...args) => console.log('inputNumber change', ...args)}
+          onNumberChange={(...args) => console.log('inputNumber number change', ...args)}
+        />
+        <Form onValueChange={v => console.log(v)}>
+          <h4>
+            Form + Form.InputNumber + formatter + onChange(onChange包括英文字符,显示没有英文字符)
+          </h4>
+          <Form.InputNumber
+            field="formOriginalInputNumber"
+            noLabel
+            formatter={value => `${value}`.replace(/\D/g, '')}
+            onChange={(...args) => console.log('form inputNumber change', ...args)}
+          />
+          <h4>
+            Form + withField InputNumber + formatter +
+            onNumberChange(onNumberChange不包括英文字符,显示也不包括英文字符)
+          </h4>
+          <CustomInput
+            field="formCustomInputNumber"
+            noLabel
+            formatter={value => `${value}`.replace(/\D/g, '')}
+          />
+        </Form>
+        <h4>
+          type=number (TODO:需要关注内置的按钮+不同浏览器对type=number的支持情况,比如 safari
+          貌似就不支持)
+        </h4>
+        <InputNumber
+          type="number"
+          onChange={(...args) => console.log('inputNumber change', ...args)}
+          onNumberChange={(...args) => console.log('inputNumber number change', ...args)}
+        />
+        <h4>测试 formatter + parser 是否正常</h4>
+        <InputNumber
+          onChange={v => console.log(`Changed to: [${typeof v}] ${v}`)}
+          defaultValue={1000}
+          min={0}
+          formatter={value => `¥ ${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')}
+          parser={value => value.replace(/\¥\s?|(,*)/g, '')}
+        />
+      </>
+    );
+  };
+  return <Demo />;
+};
+
+FormCustomInput.story = {
+  name: 'Form.CustomInput',
+};

+ 265 - 239
packages/semi-ui/layout/_story/layout.stories.js

@@ -1,279 +1,305 @@
 import React from 'react';
-import { storiesOf } from '@storybook/react'; // import { withKnobs, text, boolean } from '@storybook/addon-knobs';
 
 import { Layout } from '../index';
 import Nav from '../../navigation';
 import { Button } from '../../index';
-import { IconBytedanceLogo, IconVigoLogo, IconDescend, IconList, IconEdit, IconCamera, IconFile, IconGlobe } from '@douyinfe/semi-icons';
-const stories = storiesOf('Layout', module); // stories.addDecorator(withKnobs);;
+import {
+  IconBytedanceLogo,
+  IconVigoLogo,
+  IconDescend,
+  IconList,
+  IconEdit,
+  IconCamera,
+  IconFile,
+  IconGlobe,
+} from '@douyinfe/semi-icons';
+
+export default {
+  title: 'Layout'
+}
 
 const { Header, Footer, Sider, Content } = Layout;
 const style = {
-    textAlign: 'center',
-    margin: 60,
+  textAlign: 'center',
+  margin: 60,
 };
 const contentStyle = {
-    height: 300,
-    backgroundColor: '#ddd',
+  height: 300,
+  backgroundColor: '#ddd',
 };
 const siderStyle = {
-    width: 100,
-    backgroundColor: '#ccc',
+  width: 100,
+  backgroundColor: '#ccc',
 };
 const headerStyle = {
-    height: 64,
-    paddingLeft: 50,
-    paddingRight: 50,
-    color: '#333',
-    background: '#f0f2f5',
+  height: 64,
+  paddingLeft: 50,
+  paddingRight: 50,
+  color: '#333',
+  background: '#f0f2f5',
 };
 const footerStyle = {
-    height: 64,
-    paddingLeft: 50,
-    paddingRight: 50,
-    color: '#333',
-    background: '#f0f2f5',
+  height: 64,
+  paddingLeft: 50,
+  paddingRight: 50,
+  color: '#333',
+  background: '#f0f2f5',
 };
-stories.add('Layout default', () => (
-    <div>
-        <Layout style={style}>
-            <Header style={headerStyle}>Header</Header>
-            <Content style={contentStyle}>Content</Content>
-            <Footer style={footerStyle}>Footer</Footer>
-        </Layout>
 
-        <Layout style={style}>
-            <Header style={headerStyle}>Header</Header>
-            <Layout>
-                <Sider style={siderStyle}>Sider</Sider>
-                <Content style={contentStyle}>Content</Content>
-            </Layout>
-            <Footer style={footerStyle}>Footer</Footer>
-        </Layout>
+export const LayoutDefault = () => (
+  <div>
+    <Layout style={style}>
+      <Header style={headerStyle}>Header</Header>
+      <Content style={contentStyle}>Content</Content>
+      <Footer style={footerStyle}>Footer</Footer>
+    </Layout>
 
-        <Layout style={style}>
-            <Header style={headerStyle}>Header</Header>
-            <Layout>
-                <Content style={contentStyle}>Content</Content>
-                <Sider style={siderStyle}>Sider</Sider>
-            </Layout>
-            <Footer style={footerStyle}>Footer</Footer>
-        </Layout>
+    <Layout style={style}>
+      <Header style={headerStyle}>Header</Header>
+      <Layout>
+        <Sider style={siderStyle}>Sider</Sider>
+        <Content style={contentStyle}>Content</Content>
+      </Layout>
+      <Footer style={footerStyle}>Footer</Footer>
+    </Layout>
 
-        <Layout style={style}>
-            <Sider style={siderStyle}>Sider</Sider>
-            <Layout>
-                <Header style={headerStyle}>Header</Header>
-                <Content style={contentStyle}>Content</Content>
-                <Footer style={footerStyle}>Footer</Footer>
-            </Layout>
-        </Layout>
-    </div>
-));
-stories.add('Layout demo', () => (
-    <div>
-        <Layout style={style}>
-            <Sider>
-                <Nav
-                    style={{
-                        width: 200,
-                    }}
-                    items={[
-                        {
-                            itemKey: '1',
-                            text: 'Option 1',
-                            icon: <IconEdit />,
-                        },
-                        {
-                            itemKey: '2',
-                            text: 'Option 2',
-                            icon: <IconCamera />,
-                        },
-                        {
-                            text: 'Group 3',
-                            icon: <IconFile />,
-                            itemKey: '3',
-                            items: ['3-1', '3-2'],
-                        },
-                        {
-                            text: 'Group 4',
-                            icon: <IconGlobe />,
-                            itemKey: '4',
-                            items: ['4-1', '4-2'],
-                        },
-                    ]}
-                />
-            </Sider>
-            <Layout>
-                <Header style={headerStyle}>Header</Header>
-                <Content style={contentStyle}>Content</Content>
-                <Footer style={footerStyle}>Footer</Footer>
-            </Layout>
-        </Layout>
-    </div>
-));
+    <Layout style={style}>
+      <Header style={headerStyle}>Header</Header>
+      <Layout>
+        <Content style={contentStyle}>Content</Content>
+        <Sider style={siderStyle}>Sider</Sider>
+      </Layout>
+      <Footer style={footerStyle}>Footer</Footer>
+    </Layout>
 
-class NavApp extends React.Component {
-    constructor() {
-        super();
-        this.state = {
-            isCollapsed: true,
-            defaultOpenKeys: [],
-            mode: 'vertical',
-            navHeight: 480,
-            selectedKeys: [],
-            openKeys: [],
-        };
+    <Layout style={style}>
+      <Sider style={siderStyle}>Sider</Sider>
+      <Layout>
+        <Header style={headerStyle}>Header</Header>
+        <Content style={contentStyle}>Content</Content>
+        <Footer style={footerStyle}>Footer</Footer>
+      </Layout>
+    </Layout>
+  </div>
+);
 
-        this.onSelect = (data = {}) => {
-            console.log('trigger onSelect: ', data);
-            let selectedKeys = Array.from(data.selectedKeys);
-            this.setState({
-                selectedKeys,
-            });
-        };
+LayoutDefault.story = {
+  name: 'Layout default',
+};
 
-        this.onOpenChange = (data = {}) => {
-            console.log('trigger onOpenChange: ', data);
-            let openKeys = Array.from(data.openKeys);
-            this.setState({
-                openKeys,
-            });
-        };
-    }
+export const LayoutDemo = () => (
+  <div>
+    <Layout style={style}>
+      <Sider>
+        <Nav
+          style={{
+            width: 200,
+          }}
+          items={[
+            {
+              itemKey: '1',
+              text: 'Option 1',
+              icon: <IconEdit />,
+            },
+            {
+              itemKey: '2',
+              text: 'Option 2',
+              icon: <IconCamera />,
+            },
+            {
+              text: 'Group 3',
+              icon: <IconFile />,
+              itemKey: '3',
+              items: ['3-1', '3-2'],
+            },
+            {
+              text: 'Group 4',
+              icon: <IconGlobe />,
+              itemKey: '4',
+              items: ['4-1', '4-2'],
+            },
+          ]}
+        />
+      </Sider>
+      <Layout>
+        <Header style={headerStyle}>Header</Header>
+        <Content style={contentStyle}>Content</Content>
+        <Footer style={footerStyle}>Footer</Footer>
+      </Layout>
+    </Layout>
+  </div>
+);
 
-    updateCollapsed(isCollapsed) {
-        this.setState({
-            isCollapsed,
-        });
-    }
+LayoutDemo.story = {
+  name: 'Layout demo',
+};
 
-    toggleMode() {
-        let { mode, navHeight } = this.state;
+class NavApp extends React.Component {
+  constructor() {
+    super();
+    this.state = {
+      isCollapsed: true,
+      defaultOpenKeys: [],
+      mode: 'vertical',
+      navHeight: 480,
+      selectedKeys: [],
+      openKeys: [],
+    };
 
-        if (mode === 'vertical') {
-            mode = 'horizontal';
-            navHeight = 60;
-        } else {
-            mode = 'vertical';
-            navHeight = 480;
-        }
+    this.onSelect = (data = {}) => {
+      console.log('trigger onSelect: ', data);
+      let selectedKeys = Array.from(data.selectedKeys);
+      this.setState({
+        selectedKeys,
+      });
+    };
 
-        this.setState({
-            mode,
-            navHeight,
-        });
-    }
+    this.onOpenChange = (data = {}) => {
+      console.log('trigger onOpenChange: ', data);
+      let openKeys = Array.from(data.openKeys);
+      this.setState({
+        openKeys,
+      });
+    };
+  }
+
+  updateCollapsed(isCollapsed) {
+    this.setState({
+      isCollapsed,
+    });
+  }
 
-    render() {
-        let { isCollapsed, defaultOpenKeys, mode, navHeight, selectedKeys, openKeys } = this.state;
-        return (
-            <div>
-                <Nav
-                    isCollapsed={isCollapsed}
-                    defaultOpenKeys={defaultOpenKeys}
-                    style={{
-                        height: navHeight,
-                    }}
-                    mode={mode}
-                    selectedKeys={selectedKeys}
-                    openKeys={openKeys}
-                    onSelect={this.onSelect}
-                    onOpenChange={this.onOpenChange}
-                >
-                    <Nav.Header logo={<IconBytedanceLogo size="extra-large" />} text="互娱运营" />
-                    <Nav.Item itemKey={'1'} text={<strong>火山运营</strong>} icon={<IconVigoLogo />} />
-                    <Nav.Sub itemKey={'2'} text={<strong>运营</strong>} icon={<IconVigoLogo />}>
-                        {['2-1', '2-2'].map(k => (
-                            <Nav.Item key={k} itemKey={String(k)} text={'Option ' + k} />
-                        ))}
-                        <Nav.Sub text={'Group 2-3'} icon={<IconDescend />} itemKey="2-3">
-                            <Nav.Item itemKey={'2-3-1'} text={'Option 2-3-1'} />
-                            <Nav.Item itemKey={'2-3-2'} text={'Option 2-3-2'} />
-                        </Nav.Sub>
-                    </Nav.Sub>
-                    <Nav.Footer>
-                        <Button
-                            title="展开/收起切换"
-                            icon={<IconList />}
-                            onClick={() => this.updateCollapsed(!isCollapsed)}
-                        />
-                    </Nav.Footer>
-                </Nav>
-            </div>
-        );
+  toggleMode() {
+    let { mode, navHeight } = this.state;
+
+    if (mode === 'vertical') {
+      mode = 'horizontal';
+      navHeight = 60;
+    } else {
+      mode = 'vertical';
+      navHeight = 480;
     }
+
+    this.setState({
+      mode,
+      navHeight,
+    });
+  }
+
+  render() {
+    let { isCollapsed, defaultOpenKeys, mode, navHeight, selectedKeys, openKeys } = this.state;
+    return (
+      <div>
+        <Nav
+          isCollapsed={isCollapsed}
+          defaultOpenKeys={defaultOpenKeys}
+          style={{
+            height: navHeight,
+          }}
+          mode={mode}
+          selectedKeys={selectedKeys}
+          openKeys={openKeys}
+          onSelect={this.onSelect}
+          onOpenChange={this.onOpenChange}
+        >
+          <Nav.Header logo={<IconBytedanceLogo size="extra-large" />} text="互娱运营" />
+          <Nav.Item itemKey={'1'} text={<strong>火山运营</strong>} icon={<IconVigoLogo />} />
+          <Nav.Sub itemKey={'2'} text={<strong>运营</strong>} icon={<IconVigoLogo />}>
+            {['2-1', '2-2'].map(k => (
+              <Nav.Item key={k} itemKey={String(k)} text={'Option ' + k} />
+            ))}
+            <Nav.Sub text={'Group 2-3'} icon={<IconDescend />} itemKey="2-3">
+              <Nav.Item itemKey={'2-3-1'} text={'Option 2-3-1'} />
+              <Nav.Item itemKey={'2-3-2'} text={'Option 2-3-2'} />
+            </Nav.Sub>
+          </Nav.Sub>
+          <Nav.Footer>
+            <Button
+              title="展开/收起切换"
+              icon={<IconList />}
+              onClick={() => this.updateCollapsed(!isCollapsed)}
+            />
+          </Nav.Footer>
+        </Nav>
+      </div>
+    );
+  }
 }
 
-stories.add('collapse nav demo', () => (
-    <div>
-        <Layout style={style}>
-            <Sider>
-                <NavApp />
-            </Sider>
-            <Layout>
-                <Header style={headerStyle}>Header</Header>
-                <Content style={contentStyle}>Content</Content>
-                <Footer style={footerStyle}>Footer</Footer>
-            </Layout>
-        </Layout>
-    </div>
-));
+export const CollapseNavDemo = () => (
+  <div>
+    <Layout style={style}>
+      <Sider>
+        <NavApp />
+      </Sider>
+      <Layout>
+        <Header style={headerStyle}>Header</Header>
+        <Content style={contentStyle}>Content</Content>
+        <Footer style={footerStyle}>Footer</Footer>
+      </Layout>
+    </Layout>
+  </div>
+);
+
+CollapseNavDemo.story = {
+  name: 'collapse nav demo',
+};
 
 class SimpleNav extends React.Component {
-    constructor() {
-        super();
-        this.state = {
-            isCollapsed: true,
-            mode: 'vertical',
-            navHeight: 480,
-        };
-    }
+  constructor() {
+    super();
+    this.state = {
+      isCollapsed: true,
+      mode: 'vertical',
+      navHeight: 480,
+    };
+  }
 
-    updateCollapsed(isCollapsed) {
-        this.setState({
-            isCollapsed,
-        });
-    }
+  updateCollapsed(isCollapsed) {
+    this.setState({
+      isCollapsed,
+    });
+  }
 
-    render() {
-        let { isCollapsed, mode, navHeight } = this.state;
-        return (
-            <div>
-                <Nav
-                    isCollapsed={isCollapsed}
-                    style={{
-                        height: navHeight,
-                    }}
-                    mode={mode}
-                >
-                    <Button
-                        icon={<IconList />}
-                        onClick={() => this.updateCollapsed(!isCollapsed)}
-                    >
-                        展开/收起切换
-                    </Button>
-                </Nav>
-            </div>
-        );
-    }
+  render() {
+    let { isCollapsed, mode, navHeight } = this.state;
+    return (
+      <div>
+        <Nav
+          isCollapsed={isCollapsed}
+          style={{
+            height: navHeight,
+          }}
+          mode={mode}
+        >
+          <Button icon={<IconList />} onClick={() => this.updateCollapsed(!isCollapsed)}>
+            展开/收起切换
+          </Button>
+        </Nav>
+      </div>
+    );
+  }
 }
 
 const onbreakpoint = (screen, bool) => {
-    console.log(screen, bool);
+  console.log(screen, bool);
 };
 
-stories.add('collapse SimpleNav demo', () => (
-    <div>
-        <Layout style={style}>
-            <Sider breakpoint={['md']} onBreakpoint={onbreakpoint}>
-                <SimpleNav />
-            </Sider>
-            <Layout>
-                <Header style={headerStyle}>Header</Header>
-                <Content style={contentStyle}>Content</Content>
-                <Footer style={footerStyle}>Footer</Footer>
-            </Layout>
-        </Layout>
-    </div>
-));
+export const CollapseSimpleNavDemo = () => (
+  <div>
+    <Layout style={style}>
+      <Sider breakpoint={['md']} onBreakpoint={onbreakpoint}>
+        <SimpleNav />
+      </Sider>
+      <Layout>
+        <Header style={headerStyle}>Header</Header>
+        <Content style={contentStyle}>Content</Content>
+        <Footer style={footerStyle}>Footer</Footer>
+      </Layout>
+    </Layout>
+  </div>
+);
+
+CollapseSimpleNavDemo.story = {
+  name: 'collapse SimpleNav demo',
+};

+ 827 - 699
packages/semi-ui/list/_story/list.stories.js

@@ -5,788 +5,916 @@ import InfiniteScroll from 'react-infinite-scroller';
 import { DndProvider, DragSource, DropTarget, useDrag, useDrop } from 'react-dnd';
 import HTML5Backend from 'react-dnd-html5-backend';
 import update from 'immutability-helper';
-import { storiesOf } from '@storybook/react';
 import { Skeleton, Avatar, Button, ButtonGroup, Spin } from '../../index';
 import List from '..';
-
-import WindowScroller from 'react-virtualized/dist/commonjs/WindowScroller';
 import AutoSizer from 'react-virtualized/dist/commonjs/AutoSizer';
 import VList from 'react-virtualized/dist/commonjs/List';
 import InfiniteLoader from 'react-virtualized/dist/commonjs/InfiniteLoader';
 
-
 const Item = List.Item;
-const stories = storiesOf('List', module);
+
+
+export default {
+  title: 'List'
+}
+
 const data = [
-    '从明天起,做一个幸福的人',
-    '喂马,劈柴,周游世界',
-    '从明天起,关心粮食和蔬菜',
-    '我有一所房子,面朝大海,春暖花开'
+  '从明天起,做一个幸福的人',
+  '喂马,劈柴,周游世界',
+  '从明天起,关心粮食和蔬菜',
+  '我有一所房子,面朝大海,春暖花开',
 ];
 
-const titles = [
-    '示例标题1',
-    '示例标题2',
-    '示例标题3',
-    '示例标题4',
-    '示例标题5',
-    '示例标题6'
-];
+const titles = ['示例标题1', '示例标题2', '示例标题3', '示例标题4', '示例标题5', '示例标题6'];
+
+export const BasicList = () => (
+  <div>
+    <h3 style={{ marginBottom: 16 }}>Default Size</h3>
+    <List
+      header={<div>Header</div>}
+      footer={<div>Footer</div>}
+      bordered
+      dataSource={data}
+      renderItem={item => <Item>{item}</Item>}
+    />
+    <h3 style={{ marginBottom: 16 }}>Default Size</h3>
+    <List header={<div>Header</div>} footer={<div>Footer</div>} bordered>
+      <Item onRightClick={() => console.log('key 1')}>
+        <span>从明天起,做一个幸福的人</span>
+      </Item>
+      <Item>
+        <span>喂马,劈柴,周游世界</span>
+      </Item>
+      <Item>
+        <span>从明天起,关心粮食和蔬菜'</span>
+      </Item>
+      <Item>
+        <span>我有一所房子,面朝大海,春暖花开</span>
+      </Item>
+    </List>
+    <h3 style={{ margin: '16px 0' }}>Small Size</h3>
+    <List
+      size="small"
+      header={<div>Header</div>}
+      footer={<div>Footer</div>}
+      bordered
+      onClick={e => console.log(e.target)}
+      onRightClick={e => console.log(e.target)}
+      dataSource={data}
+      renderItem={item => <List.Item>{item}</List.Item>}
+    />
+    <h3 style={{ margin: '16px 0' }}>Large Size</h3>
+    <List
+      size="large"
+      header={<div>Header</div>}
+      footer={<div>Footer</div>}
+      bordered
+      dataSource={data}
+      renderItem={item => <List.Item>{item}</List.Item>}
+    />
+  </div>
+);
+
+BasicList.story = {
+  name: 'basic list',
+};
 
-// stories.addDecorator(withKnobs);;
+export const EmptyList = () => (
+  <div>
+    <List header={<div>Header</div>} footer={<div>Footer</div>} bordered />
+  </div>
+);
 
-stories.add('basic list', () => (
-    <div>
-        <h3 style={{ marginBottom: 16 }}>Default Size</h3>
-        <List
-            header={<div>Header</div>}
-            footer={<div>Footer</div>}
-            bordered
-            dataSource={data}
-            renderItem={item => (
-                <Item>{item}</Item>
-            )}
-        />
-        <h3 style={{ marginBottom: 16 }}>Default Size</h3>
-        <List
-            header={<div>Header</div>}
-            footer={<div>Footer</div>}
-            bordered
-        >
-            <Item onRightClick={() => console.log('key 1')}><span>从明天起,做一个幸福的人</span></Item>
-            <Item><span>喂马,劈柴,周游世界</span></Item>
-            <Item><span>从明天起,关心粮食和蔬菜'</span></Item>
-            <Item><span>我有一所房子,面朝大海,春暖花开</span></Item>
-        </List>
-        <h3 style={{ margin: '16px 0' }}>Small Size</h3>
-        <List
-            size="small"
-            header={<div>Header</div>}
-            footer={<div>Footer</div>}
-            bordered
-            onClick={(e) => console.log(e.target)}
-            onRightClick={(e) => console.log(e.target)}
-            dataSource={data}
-            renderItem={item => <List.Item>{item}</List.Item>}
-        />
-        <h3 style={{ margin: '16px 0' }}>Large Size</h3>
-        <List
-            size="large"
-            header={<div>Header</div>}
-            footer={<div>Footer</div>}
-            bordered
-            dataSource={data}
-            renderItem={item => <List.Item>{item}</List.Item>}
-        />
-    </div>
-));
-
-stories.add('empty list', () => (
-    <div>
-        <List
-            header={<div>Header</div>}
-            footer={<div>Footer</div>}
-            bordered
-        />
-    </div>
-));
+EmptyList.story = {
+  name: 'empty list',
+};
+
+export const JsxList = () => (
+  <List
+    header={<div>Header</div>}
+    footer={<div>Footer</div>}
+    bordered
+    split={false}
+    // layout="horizontal"
+    // grid
+    grid={{
+      gutter: 12,
+      span: 6,
+    }}
+  >
+    <Item>
+      <span>从明天起,做一个幸福的人</span>
+    </Item>
+    <Item>
+      <span>喂马,劈柴,周游世界</span>
+    </Item>
+    <Item>
+      <span>从明天起,关心粮食和蔬菜'</span>
+    </Item>
+    <Item>
+      <span>我有一所房子,面朝大海,春暖花开</span>
+    </Item>
+  </List>
+);
+
+JsxList.story = {
+  name: 'jsx list',
+};
 
-stories.add('jsx list', () => (
+export const NoBorder = () => (
+  <div>
     <List
-        header={<div>Header</div>}
-        footer={<div>Footer</div>}
-        bordered
-        split={false}
-        // layout="horizontal"
-        // grid
-        grid={{
-            gutter: 12,
-            span: 6,
-        }}
-    >
-        <Item><span>从明天起,做一个幸福的人</span></Item>
-        <Item><span>喂马,劈柴,周游世界</span></Item>
-        <Item><span>从明天起,关心粮食和蔬菜'</span></Item>
-        <Item><span>我有一所房子,面朝大海,春暖花开</span></Item>
-    </List>
-));
-
-stories.add('no border', () => (
-    <div>
-        <List
-            header={<div>Header</div>}
-            footer={<div>Footer</div>}
-            dataSource={data}
-            renderItem={item => <List.Item>{item}</List.Item>}
-        />
-        <br />
-        <br />
-        <List
-            header={<div>Header</div>}
-            footer={<div>Footer</div>}
-            split={false}
-            dataSource={data}
-            renderItem={item => <List.Item>{item}</List.Item>}
-        />
-    </div>
-));
+      header={<div>Header</div>}
+      footer={<div>Footer</div>}
+      dataSource={data}
+      renderItem={item => <List.Item>{item}</List.Item>}
+    />
+    <br />
+    <br />
+    <List
+      header={<div>Header</div>}
+      footer={<div>Footer</div>}
+      split={false}
+      dataSource={data}
+      renderItem={item => <List.Item>{item}</List.Item>}
+    />
+  </div>
+);
+
+NoBorder.story = {
+  name: 'no border',
+};
 
-stories.add('item structure', () => (
-    <div style={{ padding: 12, border: '1px solid var(--semi-color-border)', margin: 12 }}>
-        <List
-            dataSource={data}
-            renderItem={item => (
-                <List.Item
-                    header={<Avatar color='red' >CA</Avatar>}
-                    main={<div><span style={{ color: 'var(--semi-color-text-0)' }}>示例标题</span><p style={{ color: 'var(--semi-color-text-2)', margin: '4px 0' }}>Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统。设计系统包含设计语言以及一整套可复用的前端组件,帮助设计师与开发者更容易地打造高质量的、用户体验一致的、符合设计规范的 Web 应用。</p></div>}
-                    extra={
-                        <ButtonGroup theme='borderless'>
-                            <Button>编辑</Button>
-                            <Button>更多</Button>
-                        </ButtonGroup>
-                    }
-                />)
-            }
-        />
-    </div>
-));
-
-stories.add('item layout', () => (
-    <div style={{ padding: 12, border: '1px solid var(--semi-color-border)', margin: 12 }}>
-        <List
-            dataSource={data}
-            layout='horizontal'
-            renderItem={item => (
-                <List.Item
-                    header={<Avatar color='red' >CA</Avatar>}
-                    main={<div><span style={{ color: 'var(--semi-color-text-0)' }}>示例标题</span><p style={{ color: 'var(--semi-color-text-2)', margin: '4px 0' }}>Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统。设计系统包含设计语言以及一整套可复用的前端组件,帮助设计师与开发者更容易地打造高质量的、用户体验一致的、符合设计规范的 Web 应用。</p></div>}
-                    extra={
-                        <ButtonGroup theme='borderless'>
-                            <Button>编辑</Button>
-                            <Button>更多</Button>
-                        </ButtonGroup>
-                    }
-                />)
-            }
-        />
-    </div>
-));
-
-stories.add('item layout align', () => (
-    <div style={{ padding: 12, border: '1px solid var(--semi-color-border)', margin: 12 }}>
-        <List
-            dataSource={data}
-            layout='horizontal'
-            renderItem={item => (
-                <List.Item
-                    header={<Avatar color='red' >CA</Avatar>}
-                    main={<div><span style={{ color: 'var(--semi-color-text-0)' }}>示例标题</span><p style={{ color: 'var(--semi-color-text-2)', margin: '4px 0' }}>Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统。设计系统包含设计语言以及一整套可复用的前端组件,帮助设计师与开发者更容易地打造高质量的、用户体验一致的、符合设计规范的 Web 应用。</p></div>}
-                    align='flex-end'
-                    extra={
-                        <ButtonGroup theme='borderless'>
-                            <Button>编辑</Button>
-                            <Button>更多</Button>
-                        </ButtonGroup>
-                    }
-                />)
-            }
+export const ItemStructure = () => (
+  <div style={{ padding: 12, border: '1px solid var(--semi-color-border)', margin: 12 }}>
+    <List
+      dataSource={data}
+      renderItem={item => (
+        <List.Item
+          header={<Avatar color="red">CA</Avatar>}
+          main={
+            <div>
+              <span style={{ color: 'var(--semi-color-text-0)' }}>示例标题</span>
+              <p style={{ color: 'var(--semi-color-text-2)', margin: '4px 0' }}>
+                Semi Design 是由互娱社区前端团队与 UED
+                团队共同设计开发并维护的设计系统。设计系统包含设计语言以及一整套可复用的前端组件,帮助设计师与开发者更容易地打造高质量的、用户体验一致的、符合设计规范的
+                Web 应用。
+              </p>
+            </div>
+          }
+          extra={
+            <ButtonGroup theme="borderless">
+              <Button>编辑</Button>
+              <Button>更多</Button>
+            </ButtonGroup>
+          }
         />
-        <br />
-        <List
-            dataSource={data}
-            layout='horizontal'
-            renderItem={item => (
-                <List.Item
-                    header={<Avatar color='red' >CA</Avatar>}
-                    main={<div><span style={{ color: 'var(--semi-color-text-0)' }}>示例标题</span><p style={{ color: 'var(--semi-color-text-2)', margin: '4px 0' }}>Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统。设计系统包含设计语言以及一整套可复用的前端组件,帮助设计师与开发者更容易地打造高质量的、用户体验一致的、符合设计规范的 Web 应用。</p></div>}
-                    align='center'
-                    extra={
-                        <ButtonGroup theme='borderless'>
-                            <Button>编辑</Button>
-                            <Button>更多</Button>
-                        </ButtonGroup>
-                    }
-                />)
-            }
+      )}
+    />
+  </div>
+);
+
+ItemStructure.story = {
+  name: 'item structure',
+};
+
+export const ItemLayout = () => (
+  <div style={{ padding: 12, border: '1px solid var(--semi-color-border)', margin: 12 }}>
+    <List
+      dataSource={data}
+      layout="horizontal"
+      renderItem={item => (
+        <List.Item
+          header={<Avatar color="red">CA</Avatar>}
+          main={
+            <div>
+              <span style={{ color: 'var(--semi-color-text-0)' }}>示例标题</span>
+              <p style={{ color: 'var(--semi-color-text-2)', margin: '4px 0' }}>
+                Semi Design 是由互娱社区前端团队与 UED
+                团队共同设计开发并维护的设计系统。设计系统包含设计语言以及一整套可复用的前端组件,帮助设计师与开发者更容易地打造高质量的、用户体验一致的、符合设计规范的
+                Web 应用。
+              </p>
+            </div>
+          }
+          extra={
+            <ButtonGroup theme="borderless">
+              <Button>编辑</Button>
+              <Button>更多</Button>
+            </ButtonGroup>
+          }
         />
-        <br />
-        <List
-            dataSource={data}
-            layout='horizontal'
-            renderItem={item => (
-                <List.Item
-                    header={<Avatar color='red' >CA</Avatar>}
-                    main={<div><span style={{ color: 'var(--semi-color-text-0)' }}>示例标题</span><p style={{ color: 'var(--semi-color-text-2)', margin: '4px 0' }}>Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统。设计系统包含设计语言以及一整套可复用的前端组件,帮助设计师与开发者更容易地打造高质量的、用户体验一致的、符合设计规范的 Web 应用。</p></div>}
-                    align='baseline'
-                    extra={
-                        <ButtonGroup theme='borderless'>
-                            <Button>编辑</Button>
-                            <Button>更多</Button>
-                        </ButtonGroup>
-                    }
-                />)
-            }
+      )}
+    />
+  </div>
+);
+
+ItemLayout.story = {
+  name: 'item layout',
+};
+
+export const ItemLayoutAlign = () => (
+  <div style={{ padding: 12, border: '1px solid var(--semi-color-border)', margin: 12 }}>
+    <List
+      dataSource={data}
+      layout="horizontal"
+      renderItem={item => (
+        <List.Item
+          header={<Avatar color="red">CA</Avatar>}
+          main={
+            <div>
+              <span style={{ color: 'var(--semi-color-text-0)' }}>示例标题</span>
+              <p style={{ color: 'var(--semi-color-text-2)', margin: '4px 0' }}>
+                Semi Design 是由互娱社区前端团队与 UED
+                团队共同设计开发并维护的设计系统。设计系统包含设计语言以及一整套可复用的前端组件,帮助设计师与开发者更容易地打造高质量的、用户体验一致的、符合设计规范的
+                Web 应用。
+              </p>
+            </div>
+          }
+          align="flex-end"
+          extra={
+            <ButtonGroup theme="borderless">
+              <Button>编辑</Button>
+              <Button>更多</Button>
+            </ButtonGroup>
+          }
         />
-        <br />
-        <List
-            dataSource={data}
-            layout='horizontal'
-            renderItem={item => (
-                <List.Item
-                    header={<Avatar color='red' >CA</Avatar>}
-                    main={<div><span style={{ color: 'var(--semi-color-text-0)' }}>示例标题</span><p style={{ color: 'var(--semi-color-text-2)', margin: '4px 0' }}>Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统。设计系统包含设计语言以及一整套可复用的前端组件,帮助设计师与开发者更容易地打造高质量的、用户体验一致的、符合设计规范的 Web 应用。</p></div>}
-                    align='stretch'
-                    extra={
-                        <ButtonGroup theme='borderless'>
-                            <Button>编辑</Button>
-                            <Button>更多</Button>
-                        </ButtonGroup>
-                    }
-                />)
-            }
+      )}
+    />
+    <br />
+    <List
+      dataSource={data}
+      layout="horizontal"
+      renderItem={item => (
+        <List.Item
+          header={<Avatar color="red">CA</Avatar>}
+          main={
+            <div>
+              <span style={{ color: 'var(--semi-color-text-0)' }}>示例标题</span>
+              <p style={{ color: 'var(--semi-color-text-2)', margin: '4px 0' }}>
+                Semi Design 是由互娱社区前端团队与 UED
+                团队共同设计开发并维护的设计系统。设计系统包含设计语言以及一整套可复用的前端组件,帮助设计师与开发者更容易地打造高质量的、用户体验一致的、符合设计规范的
+                Web 应用。
+              </p>
+            </div>
+          }
+          align="center"
+          extra={
+            <ButtonGroup theme="borderless">
+              <Button>编辑</Button>
+              <Button>更多</Button>
+            </ButtonGroup>
+          }
         />
-    </div>
-));
-
-stories.add('grid', () => (
-    <div style={{ padding: 12, border: '1px solid var(--semi-color-border)', margin: 12 }}>
-        <List
-            grid={{
-                gutter: 24,
-                span: 6,
-            }}
-            dataSource={data}
-            renderItem={item => (
-                <List.Item>
-                    <div style={{ border: '1px solid var(--semi-color-border)', height: '50px' }}>{item}</div>
-                </List.Item>
-            )}
+      )}
+    />
+    <br />
+    <List
+      dataSource={data}
+      layout="horizontal"
+      renderItem={item => (
+        <List.Item
+          header={<Avatar color="red">CA</Avatar>}
+          main={
+            <div>
+              <span style={{ color: 'var(--semi-color-text-0)' }}>示例标题</span>
+              <p style={{ color: 'var(--semi-color-text-2)', margin: '4px 0' }}>
+                Semi Design 是由互娱社区前端团队与 UED
+                团队共同设计开发并维护的设计系统。设计系统包含设计语言以及一整套可复用的前端组件,帮助设计师与开发者更容易地打造高质量的、用户体验一致的、符合设计规范的
+                Web 应用。
+              </p>
+            </div>
+          }
+          align="baseline"
+          extra={
+            <ButtonGroup theme="borderless">
+              <Button>编辑</Button>
+              <Button>更多</Button>
+            </ButtonGroup>
+          }
         />
-    </div>
-));
-
-stories.add('responsive grid', () => (
-    <div style={{ padding: 12, border: '1px solid var(--semi-color-border)', margin: 12 }}>
-        <List
-            grid={{
-                gutter: 16,
-                xs: 24,
-                sm: 12,
-                md: 6,
-                lg: 6,
-                xl: 4,
-                xxl: 8,
-            }}
-            dataSource={titles}
-            renderItem={item => (
-                <List.Item
-                    style={{ padding: 12 }}
-                    header={<Avatar color='red' >CA</Avatar>}
-                    main={<div><span style={{ color: 'var(--semi-color-text-0)' }}>示例标题</span><p style={{ color: 'var(--semi-color-text-2)', margin: '4px 0' }}>Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统。</p></div>}
-                    extra={
-                        <ButtonGroup theme='borderless'>
-                            <Button>编辑</Button>
-                            <Button>更多</Button>
-                        </ButtonGroup>
-                    }
-                />)
-            }
+      )}
+    />
+    <br />
+    <List
+      dataSource={data}
+      layout="horizontal"
+      renderItem={item => (
+        <List.Item
+          header={<Avatar color="red">CA</Avatar>}
+          main={
+            <div>
+              <span style={{ color: 'var(--semi-color-text-0)' }}>示例标题</span>
+              <p style={{ color: 'var(--semi-color-text-2)', margin: '4px 0' }}>
+                Semi Design 是由互娱社区前端团队与 UED
+                团队共同设计开发并维护的设计系统。设计系统包含设计语言以及一整套可复用的前端组件,帮助设计师与开发者更容易地打造高质量的、用户体验一致的、符合设计规范的
+                Web 应用。
+              </p>
+            </div>
+          }
+          align="stretch"
+          extra={
+            <ButtonGroup theme="borderless">
+              <Button>编辑</Button>
+              <Button>更多</Button>
+            </ButtonGroup>
+          }
         />
-    </div>
-));
+      )}
+    />
+  </div>
+);
 
+ItemLayoutAlign.story = {
+  name: 'item layout align',
+};
 
-class LoadMoreList extends React.Component {
-    constructor() {
-        super();
-
-        const count = 3;
-        const dataList = [];
-        for (let i = 0; i < 40; i++) {
-            dataList.push({
-                color: 'grey',
-                title: `Semi Design Title ${i}`,
-                loading: false,
-            });
-        }
-        this.data = dataList;
-        this.count = 0;
-
-        this.fetchData = () => {
-            let placeholders = [0, 1, 2].map(key => ({ loading: true }));
-            this.setState({
-                loading: true,
-                list: [...this.state.dataSource, ...placeholders],
-            });
-            return new Promise((res, rej) => {
-                setTimeout(() => {
-                    let dataSource = this.data.slice(this.count * count, this.count * count + count);
-                    res(dataSource);
-                }, 1500);
-            }).then(dataSource => {
-                let newData = [...this.state.dataSource, ...dataSource];
-                this.setState({
-                    loading: false,
-                    dataSource: newData,
-                    list: newData,
-                    noMore: !dataSource.length,
-                });
-            });
-        }
+export const Grid = () => (
+  <div style={{ padding: 12, border: '1px solid var(--semi-color-border)', margin: 12 }}>
+    <List
+      grid={{
+        gutter: 24,
+        span: 6,
+      }}
+      dataSource={data}
+      renderItem={item => (
+        <List.Item>
+          <div style={{ border: '1px solid var(--semi-color-border)', height: '50px' }}>{item}</div>
+        </List.Item>
+      )}
+    />
+  </div>
+);
+
+Grid.story = {
+  name: 'grid',
+};
 
-        this.state = {
-            loading: false,
-            dataSource: [],
-            list: [],
-            noMore: false
-        };
-    }
+export const ResponsiveGrid = () => (
+  <div style={{ padding: 12, border: '1px solid var(--semi-color-border)', margin: 12 }}>
+    <List
+      grid={{
+        gutter: 16,
+        xs: 24,
+        sm: 12,
+        md: 6,
+        lg: 6,
+        xl: 4,
+        xxl: 8,
+      }}
+      dataSource={titles}
+      renderItem={item => (
+        <List.Item
+          style={{ padding: 12 }}
+          header={<Avatar color="red">CA</Avatar>}
+          main={
+            <div>
+              <span style={{ color: 'var(--semi-color-text-0)' }}>示例标题</span>
+              <p style={{ color: 'var(--semi-color-text-2)', margin: '4px 0' }}>
+                Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统。
+              </p>
+            </div>
+          }
+          extra={
+            <ButtonGroup theme="borderless">
+              <Button>编辑</Button>
+              <Button>更多</Button>
+            </ButtonGroup>
+          }
+        />
+      )}
+    />
+  </div>
+);
 
-    componentDidMount() {
-        this.fetchData();
-    }
+ResponsiveGrid.story = {
+  name: 'responsive grid',
+};
 
-    onLoadMore() {
-        this.count++;
-        this.fetchData();
+class LoadMoreList extends React.Component {
+  constructor() {
+    super();
+
+    const count = 3;
+    const dataList = [];
+    for (let i = 0; i < 40; i++) {
+      dataList.push({
+        color: 'grey',
+        title: `Semi Design Title ${i}`,
+        loading: false,
+      });
     }
+    this.data = dataList;
+    this.count = 0;
+
+    this.fetchData = () => {
+      let placeholders = [0, 1, 2].map(key => ({ loading: true }));
+      this.setState({
+        loading: true,
+        list: [...this.state.dataSource, ...placeholders],
+      });
+      return new Promise((res, rej) => {
+        setTimeout(() => {
+          let dataSource = this.data.slice(this.count * count, this.count * count + count);
+          res(dataSource);
+        }, 1500);
+      }).then(dataSource => {
+        let newData = [...this.state.dataSource, ...dataSource];
+        this.setState({
+          loading: false,
+          dataSource: newData,
+          list: newData,
+          noMore: !dataSource.length,
+        });
+      });
+    };
 
-    render() {
-        const { loading, list, noMore } = this.state;
-        const loadMore = !loading && !noMore ? (
-            <div
-                style={{
-                    textAlign: 'center',
-                    marginTop: 12,
-                    height: 32,
-                    lineHeight: '32px',
-                }}
-            >
-                <Button onClick={() => this.onLoadMore()}>显示更多</Button>
-            </div>
-        ) : null;
-
-        const placeholder = (
-            <div style={{ display: 'flex', alignItems: 'flex-start', padding: 12, borderBottom: '1px solid var(--semi-color-border)' }}>
-                <Skeleton.Avatar style={{ marginRight: 12 }} />
+    this.state = {
+      loading: false,
+      dataSource: [],
+      list: [],
+      noMore: false,
+    };
+  }
+
+  componentDidMount() {
+    this.fetchData();
+  }
+
+  onLoadMore() {
+    this.count++;
+    this.fetchData();
+  }
+
+  render() {
+    const { loading, list, noMore } = this.state;
+    const loadMore =
+      !loading && !noMore ? (
+        <div
+          style={{
+            textAlign: 'center',
+            marginTop: 12,
+            height: 32,
+            lineHeight: '32px',
+          }}
+        >
+          <Button onClick={() => this.onLoadMore()}>显示更多</Button>
+        </div>
+      ) : null;
+
+    const placeholder = (
+      <div
+        style={{
+          display: 'flex',
+          alignItems: 'flex-start',
+          padding: 12,
+          borderBottom: '1px solid var(--semi-color-border)',
+        }}
+      >
+        <Skeleton.Avatar style={{ marginRight: 12 }} />
+        <div>
+          <Skeleton.Title style={{ width: 120, marginBottom: 12, marginTop: 12 }} />
+          <Skeleton.Paragraph style={{ width: 600 }} rows={2} />
+        </div>
+      </div>
+    );
+    return (
+      <List
+        loading={loading}
+        loadMore={loadMore}
+        dataSource={list}
+        renderItem={item => (
+          <Skeleton placeholder={placeholder} loading={item.loading}>
+            <List.Item
+              header={<Avatar color={item.color}>SE</Avatar>}
+              main={
                 <div>
-                    <Skeleton.Title style={{ width: 120, marginBottom: 12, marginTop: 12 }} />
-                    <Skeleton.Paragraph style={{ width: 600 }} rows={2} />
+                  <span style={{ color: 'var(--semi-color-text-0)', fontWeight: 500 }}>
+                    {item.title}
+                  </span>
+                  <p style={{ color: 'var(--semi-color-text-2)', margin: '4px 0' }}>
+                    Semi Design
+                    设计系统包含设计语言以及一整套可复用的前端组件,帮助设计师与开发者更容易地打造高质量的、用户体验一致的、符合设计规范的
+                    Web 应用。
+                  </p>
                 </div>
-            </div>
-        )
-        return (
-            <List
-                loading={loading}
-                loadMore={loadMore}
-                dataSource={list}
-                renderItem={item => (
-                    <Skeleton placeholder={placeholder} loading={item.loading}>
-                        <List.Item
-                            header={<Avatar color={item.color} >SE</Avatar>}
-                            main={
-                                <div>
-                                    <span style={{ color: 'var(--semi-color-text-0)', fontWeight: 500 }}>{item.title}</span>
-                                    <p style={{ color: 'var(--semi-color-text-2)', margin: '4px 0' }}>
-                                        Semi Design 设计系统包含设计语言以及一整套可复用的前端组件,帮助设计师与开发者更容易地打造高质量的、用户体验一致的、符合设计规范的 Web 应用。
-                                </p>
-                                </div>
-                            }
-                        />
-                    </Skeleton>
-                )}
+              }
             />
-        );
-    }
+          </Skeleton>
+        )}
+      />
+    );
+  }
 }
-stories.add('load more', () => <LoadMoreList />);
+export const LoadMore = () => <LoadMoreList />;
 
+LoadMore.story = {
+  name: 'load more',
+};
 
 class ScrollLoad extends React.Component {
-    constructor() {
-        super();
-
-        const count = 6;
-        const dataList = [];
-        for (let i = 0; i < 100; i++) {
-            dataList.push({
-                color: 'grey',
-                title: `Semi Design Title ${i}`,
-                loading: false,
-            });
-        }
-        this.data = dataList;
-        this.count = 0;
-
-        this.fetchData = () => {
-            this.setState({
-                loading: true,
-            });
-            return new Promise((res, rej) => {
-                setTimeout(() => {
-                    let dataSource = this.data.slice(this.count * count, this.count * count + count);
-                    res(dataSource);
-                }, 1500);
-            }).then(dataSource => {
-                let newData = [...this.state.dataSource, ...dataSource];
-                this.count++;
-                this.setState({
-                    loading: false,
-                    dataSource: newData,
-                    noMore: !dataSource.length,
-                });
-            });
-        }
-
-        this.state = {
-            loading: false,
-            dataSource: [],
-            hasMore: true,
-        };
-    }
-
-    componentDidMount() {
-        this.fetchData();
+  constructor() {
+    super();
+
+    const count = 6;
+    const dataList = [];
+    for (let i = 0; i < 100; i++) {
+      dataList.push({
+        color: 'grey',
+        title: `Semi Design Title ${i}`,
+        loading: false,
+      });
     }
+    this.data = dataList;
+    this.count = 0;
+
+    this.fetchData = () => {
+      this.setState({
+        loading: true,
+      });
+      return new Promise((res, rej) => {
+        setTimeout(() => {
+          let dataSource = this.data.slice(this.count * count, this.count * count + count);
+          res(dataSource);
+        }, 1500);
+      }).then(dataSource => {
+        let newData = [...this.state.dataSource, ...dataSource];
+        this.count++;
+        this.setState({
+          loading: false,
+          dataSource: newData,
+          noMore: !dataSource.length,
+        });
+      });
+    };
 
-    render() {
-        const { loading, dataSource, hasMore } = this.state;
-        const showLoadMore = this.count % 3 === 0;
-        const loadMore = !loading && hasMore && showLoadMore ? (
-            <div
-                style={{
-                    textAlign: 'center',
-                    marginTop: 12,
-                    height: 32,
-                    lineHeight: '32px',
-                }}
-            >
-                <Button onClick={this.fetchData}>显示更多</Button>
-            </div>
-        ) : null;
-
-        return (
-            <div className="demo-infinite-container" style={{ height: 420, overflow: 'auto' }}>
-                <InfiniteScroll
-                    initialLoad={false}
-                    pageStart={0}
-                    threshold={20}
-                    loadMore={this.fetchData}
-                    hasMore={!this.state.loading && this.state.hasMore && !showLoadMore}
-                    useWindow={false}
-                >
-                    <List
-                        loadMore={loadMore}
-                        dataSource={dataSource}
-                        renderItem={item => (
-                            <List.Item
-                                header={<Avatar color={item.color} >SE</Avatar>}
-                                main={
-                                    <div>
-                                        <span style={{ color: 'var(--semi-color-text-0)', fontWeight: 500 }}>{item.title}</span>
-                                        <p style={{ color: 'var(--semi-color-text-2)', margin: '4px 0' }}>
-                                            Semi Design 设计系统包含设计语言以及一整套可复用的前端组件,帮助设计师与开发者更容易地打造高质量的、用户体验一致的、符合设计规范的 Web 应用。
-                                        </p>
-                                    </div>
-                                }
-                            />
-                        )}
-                    />
-                    {this.state.loading && this.state.hasMore && (
-                        <div style={{ textAlign: 'center' }}>
-                            <Spin />
-                        </div>
-                    )}
-                </InfiniteScroll>
+    this.state = {
+      loading: false,
+      dataSource: [],
+      hasMore: true,
+    };
+  }
+
+  componentDidMount() {
+    this.fetchData();
+  }
+
+  render() {
+    const { loading, dataSource, hasMore } = this.state;
+    const showLoadMore = this.count % 3 === 0;
+    const loadMore =
+      !loading && hasMore && showLoadMore ? (
+        <div
+          style={{
+            textAlign: 'center',
+            marginTop: 12,
+            height: 32,
+            lineHeight: '32px',
+          }}
+        >
+          <Button onClick={this.fetchData}>显示更多</Button>
+        </div>
+      ) : null;
+
+    return (
+      <div className="demo-infinite-container" style={{ height: 420, overflow: 'auto' }}>
+        <InfiniteScroll
+          initialLoad={false}
+          pageStart={0}
+          threshold={20}
+          loadMore={this.fetchData}
+          hasMore={!this.state.loading && this.state.hasMore && !showLoadMore}
+          useWindow={false}
+        >
+          <List
+            loadMore={loadMore}
+            dataSource={dataSource}
+            renderItem={item => (
+              <List.Item
+                header={<Avatar color={item.color}>SE</Avatar>}
+                main={
+                  <div>
+                    <span style={{ color: 'var(--semi-color-text-0)', fontWeight: 500 }}>
+                      {item.title}
+                    </span>
+                    <p style={{ color: 'var(--semi-color-text-2)', margin: '4px 0' }}>
+                      Semi Design
+                      设计系统包含设计语言以及一整套可复用的前端组件,帮助设计师与开发者更容易地打造高质量的、用户体验一致的、符合设计规范的
+                      Web 应用。
+                    </p>
+                  </div>
+                }
+              />
+            )}
+          />
+          {this.state.loading && this.state.hasMore && (
+            <div style={{ textAlign: 'center' }}>
+              <Spin />
             </div>
-        );
-    }
+          )}
+        </InfiniteScroll>
+      </div>
+    );
+  }
 }
-stories.add('scroll load', () => <ScrollLoad />);
+export const _ScrollLoad = () => <ScrollLoad />;
+
+_ScrollLoad.story = {
+  name: 'scroll load',
+};
 
 const listItems = [
-    {
-        title: 'Semi Design Title 1',
-        color: 'red',
-    },
-    {
-        title: 'Semi Design Title 2',
-        color: 'grey'
-    },
-    {
-        title: 'Semi Design Title 3',
-        color: 'light-green',
-    },
-    {
-        title: 'Semi Design Title 4',
-        color: 'light-blue',
-    },
-    {
-        title: 'Semi Design Title 5',
-        color: 'pink',
-    }
+  {
+    title: 'Semi Design Title 1',
+    color: 'red',
+  },
+  {
+    title: 'Semi Design Title 2',
+    color: 'grey',
+  },
+  {
+    title: 'Semi Design Title 3',
+    color: 'light-green',
+  },
+  {
+    title: 'Semi Design Title 4',
+    color: 'light-blue',
+  },
+  {
+    title: 'Semi Design Title 5',
+    color: 'pink',
+  },
 ];
 
 const cardSource = {
-    beginDrag(props) {
-        return {
-            id: props.id,
-            index: props.index
-        };
-    }
+  beginDrag(props) {
+    return {
+      id: props.id,
+      index: props.index,
+    };
+  },
 };
 
 const cardTarget = {
-    hover(props, monitor, component) {
-        // test demo below is from react-dnd and react-dnd-html5-backend. https://react-dnd.github.io/react-dnd/about
-        const dragIndex = monitor.getItem().index;
-        const hoverIndex = props.index;
-
-        if (dragIndex === hoverIndex) {
-            return;
-        }
-        const hoverBoundingRect = ReactDOM.findDOMNode(component).getBoundingClientRect();
-        const hoverMiddleY = (hoverBoundingRect.bottom - hoverBoundingRect.top) / 2;
-        const clientOffset = monitor.getClientOffset();
-        const hoverClientY = clientOffset.y - hoverBoundingRect.top;
-        if (dragIndex < hoverIndex && hoverClientY < hoverMiddleY) {
-            return;
-        }
+  hover(props, monitor, component) {
+    // test demo below is from react-dnd and react-dnd-html5-backend. https://react-dnd.github.io/react-dnd/about
+    const dragIndex = monitor.getItem().index;
+    const hoverIndex = props.index;
 
-        if (dragIndex > hoverIndex && hoverClientY > hoverMiddleY) {
-            return;
-        }
+    if (dragIndex === hoverIndex) {
+      return;
+    }
+    const hoverBoundingRect = ReactDOM.findDOMNode(component).getBoundingClientRect();
+    const hoverMiddleY = (hoverBoundingRect.bottom - hoverBoundingRect.top) / 2;
+    const clientOffset = monitor.getClientOffset();
+    const hoverClientY = clientOffset.y - hoverBoundingRect.top;
+    if (dragIndex < hoverIndex && hoverClientY < hoverMiddleY) {
+      return;
+    }
 
-        monitor.getItem().index = hoverIndex;
-        props.moveItem(dragIndex, hoverIndex);
+    if (dragIndex > hoverIndex && hoverClientY > hoverMiddleY) {
+      return;
     }
+
+    monitor.getItem().index = hoverIndex;
+    props.moveItem(dragIndex, hoverIndex);
+  },
 };
 
 function collectDragSource(connect, monitor) {
-    return {
-        connectDragSource: connect.dragSource(),
-        // isDragging: monitor.isDragging()
-        draggingItem: monitor.getItem()
-    };
+  return {
+    connectDragSource: connect.dragSource(),
+    // isDragging: monitor.isDragging()
+    draggingItem: monitor.getItem(),
+  };
 }
 
 function collectDropTarget(connect) {
-    return {
-        connectDropTarget: connect.dropTarget()
-    };
+  return {
+    connectDropTarget: connect.dropTarget(),
+  };
 }
 
 class DraggableItem extends React.Component {
-    render() {
-        const { component, draggingItem, index, connectDragSource, connectDropTarget } = this.props;
-        const opacity = draggingItem && draggingItem.index === index ? .3 : 1;
-        const style = {
-            border: '1px solid var(--semi-color-border)',
-            marginBottom: 12,
-            backgroundColor: 'white',
-            cursor: 'move',
-        }
+  render() {
+    const { component, draggingItem, index, connectDragSource, connectDropTarget } = this.props;
+    const opacity = draggingItem && draggingItem.index === index ? 0.3 : 1;
+    const style = {
+      border: '1px solid var(--semi-color-border)',
+      marginBottom: 12,
+      backgroundColor: 'white',
+      cursor: 'move',
+    };
 
-        return connectDragSource(connectDropTarget(
-            <div ref={node => this.node = node} style={{ ...style, opacity }}>
-                {component}
-            </div>
-        ));
-    }
+    return connectDragSource(
+      connectDropTarget(
+        <div ref={node => (this.node = node)} style={{ ...style, opacity }}>
+          {component}
+        </div>
+      )
+    );
+  }
 }
 
 DraggableItem = DragSource('item', cardSource, collectDragSource)(DraggableItem);
 DraggableItem = DropTarget('item', cardTarget, collectDropTarget)(DraggableItem);
 
 class DraggableList extends React.Component {
-    constructor() {
-        super();
-        this.state = {
-            data: listItems,
+  constructor() {
+    super();
+    this.state = {
+      data: listItems,
+    };
+  }
+
+  moveItem = (dragIndex, hoverIndex) => {
+    const { data } = this.state;
+    const draggingItem = data[dragIndex];
+    this.setState(
+      update(this.state, {
+        data: {
+          $splice: [
+            [dragIndex, 1],
+            [hoverIndex, 0, draggingItem],
+          ],
+        },
+      })
+    );
+  };
+
+  renderDraggable = (item, id) => {
+    const content = (
+      <List.Item
+        header={<Avatar color={item.color}>SE</Avatar>}
+        main={
+          <div>
+            <span style={{ color: 'var(--semi-color-text-0)', fontWeight: 500 }}>{item.title}</span>
+            <p style={{ color: 'var(--semi-color-text-2)', margin: '4px 0' }}>
+              Semi Design
+              设计系统包含设计语言以及一整套可复用的前端组件,帮助设计师与开发者更容易地打造高质量的、用户体验一致的、符合设计规范的
+              Web 应用。
+            </p>
+          </div>
         }
-    }
-
-    moveItem = (dragIndex, hoverIndex) => {
-        const { data } = this.state;
-        const draggingItem = data[dragIndex];
-        this.setState(update(this.state, {
-            data: {
-                $splice: [
-                    [dragIndex, 1],
-                    [hoverIndex, 0, draggingItem]
-                ]
-            }
-        }))
-    }
-
-    renderDraggable = (item, id) => {
-        const content = (
-            <List.Item
-                header={<Avatar color={item.color} >SE</Avatar>}
-                main={
-                    <div>
-                        <span style={{ color: 'var(--semi-color-text-0)', fontWeight: 500 }}>{item.title}</span>
-                        <p style={{ color: 'var(--semi-color-text-2)', margin: '4px 0' }}>
-                            Semi Design 设计系统包含设计语言以及一整套可复用的前端组件,帮助设计师与开发者更容易地打造高质量的、用户体验一致的、符合设计规范的 Web 应用。
-                        </p>
-                    </div>
-                }
-            />
-        )
-        return (
-            <DraggableItem
-                key={item.title}
-                index={id}
-                id={item.title}
-                component={content}
-                moveItem={this.moveItem}
-            />
-        );
-    }
-
-    render() {
-        const { data } = this.state;
-        return (
-            <div style={{ padding: 12, border: '1px solid var(--semi-color-border)', margin: 12 }}>
-                <DndProvider backend={HTML5Backend}>
-                    <List
-                        dataSource={data}
-                        renderItem={this.renderDraggable}
-                    />
-                </DndProvider>
-            </div>
-        )
-    }
+      />
+    );
+    return (
+      <DraggableItem
+        key={item.title}
+        index={id}
+        id={item.title}
+        component={content}
+        moveItem={this.moveItem}
+      />
+    );
+  };
+
+  render() {
+    const { data } = this.state;
+    return (
+      <div style={{ padding: 12, border: '1px solid var(--semi-color-border)', margin: 12 }}>
+        <DndProvider backend={HTML5Backend}>
+          <List dataSource={data} renderItem={this.renderDraggable} />
+        </DndProvider>
+      </div>
+    );
+  }
 }
 
-stories.add('draggable', () => <DraggableList />);
-
+export const Draggable = () => <DraggableList />;
 
+Draggable.story = {
+  name: 'draggable',
+};
 
 class VirtualizedScroll extends React.Component {
-    constructor() {
-        super();
-
-        const dataList = [];
-        for (let i = 0; i < 50; i++) {
-            dataList.push({
-                color: 'grey',
-                title: `Semi Design Title ${i}`,
-            });
-        }
-        this.data = dataList;
-
-        this.fetchData = (startIndex, stopIndex) => {
-            return new Promise((res, rej) => {
-                setTimeout(() => {
-                    let dataSource = this.data.slice(startIndex, stopIndex + 1);
-                    res(dataSource);
-                }, 1000);
-            }).then(dataSource => {
-                let newData = [...this.state.dataSource, ...dataSource];
-                const { loadedRowsMap, loadingRowCount } = this.state;
-                const increment = stopIndex - startIndex + 1;
-                for (let i = startIndex; i <= stopIndex; i++) {
-                    loadedRowsMap[i] = this.statusLoaded;
-                }
-                this.setState({
-                    dataSource: newData,
-                    loadedRowsMap,
-                    loadingRowCount: loadingRowCount - increment,
-                });
-            });
-        }
-
-        this.state = {
-            dataSource: [],
-            loadedRowsMap: {},
-            loadingRowCount: 0,
-        };
-
-        this.statusLoading = 0;
-        this.statusLoaded = 1;
-        this.loadLimit = this.data.length;
-        this.renderItem = this.renderItem.bind(this);
-        this.fetchData = this.fetchData.bind(this);
-        this.handleInfiniteOnLoad = this.handleInfiniteOnLoad.bind(this);
-        this.isRowLoaded = this.isRowLoaded.bind(this);
+  constructor() {
+    super();
+
+    const dataList = [];
+    for (let i = 0; i < 50; i++) {
+      dataList.push({
+        color: 'grey',
+        title: `Semi Design Title ${i}`,
+      });
     }
-
-    handleInfiniteOnLoad({ startIndex, stopIndex }) {
-        let { dataSource, loadedRowsMap, loadingRowCount } = this.state;
+    this.data = dataList;
+
+    this.fetchData = (startIndex, stopIndex) => {
+      return new Promise((res, rej) => {
+        setTimeout(() => {
+          let dataSource = this.data.slice(startIndex, stopIndex + 1);
+          res(dataSource);
+        }, 1000);
+      }).then(dataSource => {
+        let newData = [...this.state.dataSource, ...dataSource];
+        const { loadedRowsMap, loadingRowCount } = this.state;
         const increment = stopIndex - startIndex + 1;
-        if (stopIndex >= this.loadLimit || loadingRowCount > 0) {
-            return;
-        }
         for (let i = startIndex; i <= stopIndex; i++) {
-            loadedRowsMap[i] = this.statusLoading;
+          loadedRowsMap[i] = this.statusLoaded;
         }
         this.setState({
-            loadingRowCount: loadingRowCount + increment,
+          dataSource: newData,
+          loadedRowsMap,
+          loadingRowCount: loadingRowCount - increment,
         });
-        return this.fetchData(startIndex, stopIndex);
-    }
-
-    isRowLoaded({ index }) {
-        const { loadedRowsMap } = this.state;
-        return !!loadedRowsMap[index];
+      });
     };
 
-    renderItem({ index, key, style }) {
-        const { dataSource, loadedRowsMap } = this.state;
-        const item = dataSource[index];
+    this.state = {
+      dataSource: [],
+      loadedRowsMap: {},
+      loadingRowCount: 0,
+    };
 
-        if (!item) {
-            return;
-        }
-        const content = (
-            <List.Item
-                key={key}
-                style={style}
-                header={<Avatar color={item.color} >SE</Avatar>}
-                main={
-                    <div>
-                        <span style={{ color: 'var(--semi-color-text-0)', fontWeight: 500 }}>{item.title}</span>
-                        <p style={{ color: 'var(--semi-color-text-2)', margin: '4px 0' }}>
-                            Semi Design 设计系统包含设计语言以及一整套可复用的前端组件,帮助设计师与开发者更容易地打造高质量的、用户体验一致的、符合设计规范的 Web 应用。
-                        </p>
-                    </div>
-                }
-            />
-        );
-        return content;
+    this.statusLoading = 0;
+    this.statusLoaded = 1;
+    this.loadLimit = this.data.length;
+    this.renderItem = this.renderItem.bind(this);
+    this.fetchData = this.fetchData.bind(this);
+    this.handleInfiniteOnLoad = this.handleInfiniteOnLoad.bind(this);
+    this.isRowLoaded = this.isRowLoaded.bind(this);
+  }
+
+  handleInfiniteOnLoad({ startIndex, stopIndex }) {
+    let { dataSource, loadedRowsMap, loadingRowCount } = this.state;
+    const increment = stopIndex - startIndex + 1;
+    if (stopIndex >= this.loadLimit || loadingRowCount > 0) {
+      return;
     }
-
-    render() {
-        const { dataSource } = this.state;
-        const height = 500;
-        return (
-            <List style={{ border: '1px solid var(--semi-color-border)', padding: 10 }}>
-                <InfiniteLoader
-                    isRowLoaded={this.isRowLoaded}
-                    loadMoreRows={this.handleInfiniteOnLoad}
-                    rowCount={this.loadLimit}
-                >
-                    {({ onRowsRendered, registerChild }) => (
-                        <AutoSizer disableHeight>
-                            {({ width }) => (
-                                <VList
-                                    ref={registerChild}
-                                    height={height}
-                                    onRowsRendered={onRowsRendered}
-                                    rowCount={this.loadLimit}
-                                    rowHeight={118}
-                                    rowRenderer={this.renderItem}
-                                    width={width}
-                                />
-                            )}
-                        </AutoSizer>
-                    )}
-                </InfiniteLoader>
-            </List>
-        );
+    for (let i = startIndex; i <= stopIndex; i++) {
+      loadedRowsMap[i] = this.statusLoading;
     }
+    this.setState({
+      loadingRowCount: loadingRowCount + increment,
+    });
+    return this.fetchData(startIndex, stopIndex);
+  }
+
+  isRowLoaded({ index }) {
+    const { loadedRowsMap } = this.state;
+    return !!loadedRowsMap[index];
+  }
+
+  renderItem({ index, key, style }) {
+    const { dataSource, loadedRowsMap } = this.state;
+    const item = dataSource[index];
+
+    if (!item) {
+      return;
+    }
+    const content = (
+      <List.Item
+        key={key}
+        style={style}
+        header={<Avatar color={item.color}>SE</Avatar>}
+        main={
+          <div>
+            <span style={{ color: 'var(--semi-color-text-0)', fontWeight: 500 }}>{item.title}</span>
+            <p style={{ color: 'var(--semi-color-text-2)', margin: '4px 0' }}>
+              Semi Design
+              设计系统包含设计语言以及一整套可复用的前端组件,帮助设计师与开发者更容易地打造高质量的、用户体验一致的、符合设计规范的
+              Web 应用。
+            </p>
+          </div>
+        }
+      />
+    );
+    return content;
+  }
+
+  render() {
+    const { dataSource } = this.state;
+    const height = 500;
+    return (
+      <List style={{ border: '1px solid var(--semi-color-border)', padding: 10 }}>
+        <InfiniteLoader
+          isRowLoaded={this.isRowLoaded}
+          loadMoreRows={this.handleInfiniteOnLoad}
+          rowCount={this.loadLimit}
+        >
+          {({ onRowsRendered, registerChild }) => (
+            <AutoSizer disableHeight>
+              {({ width }) => (
+                <VList
+                  ref={registerChild}
+                  height={height}
+                  onRowsRendered={onRowsRendered}
+                  rowCount={this.loadLimit}
+                  rowHeight={118}
+                  rowRenderer={this.renderItem}
+                  width={width}
+                />
+              )}
+            </AutoSizer>
+          )}
+        </InfiniteLoader>
+      </List>
+    );
+  }
 }
 
+export const Virtualized = () => <VirtualizedScroll />;
 
-stories.add('virtualized', () => <VirtualizedScroll />);
+Virtualized.story = {
+  name: 'virtualized',
+};

+ 188 - 150
packages/semi-ui/locale/_story/locale.stories.js

@@ -1,7 +1,15 @@
 import React from 'react';
-import { storiesOf } from '@storybook/react';
 import { useState } from 'react';
-import { Modal, Pagination, DatePicker, TimePicker, Table, Select, Button, Cascader } from '../../index';
+import {
+  Modal,
+  Pagination,
+  DatePicker,
+  TimePicker,
+  Select,
+  Button,
+  Cascader,
+  LocaleProvider
+} from '../../index';
 
 import zh_CN from '@douyinfe/semi-ui/locale/source/zh_CN';
 import en_GB from '@douyinfe/semi-ui/locale/source/en_GB';
@@ -11,9 +19,11 @@ import ja_JP from '@douyinfe/semi-ui/locale/source/ja_JP';
 import ru_RU from '@douyinfe/semi-ui/locale/source/ru_RU';
 import vi_VN from '@douyinfe/semi-ui/locale/source/vi_VN';
 
-import { LocaleProvider } from '@douyinfe/semi-ui';
+const { Option } = Select;
 
-const stories = storiesOf('Locale', module);
+export default {
+  title: 'LocaleProvider'
+}
 // -√ Pagination
 // -√ Modal
 // -× DatePicker
@@ -25,159 +35,187 @@ const stories = storiesOf('Locale', module);
 const TableDemo = () => {};
 
 const CascaderDemo = () => {
-    const treeData = [
+  const treeData = [
+    {
+      label: '亚洲',
+      value: 'yazhou',
+      children: [
+        {
+          label: '中国',
+          value: 'zhongguo',
+          children: [
+            {
+              label: '北京',
+              value: 'beijing',
+            },
+            {
+              label: '上海',
+              value: 'shanghai',
+            },
+          ],
+        },
         {
-            label: '亚洲',
-            value: 'yazhou',
-            children: [
-                {
-                    label: '中国',
-                    value: 'zhongguo',
-                    children: [
-                        {
-                            label: '北京',
-                            value: 'beijing',
-                        },
-                        {
-                            label: '上海',
-                            value: 'shanghai',
-                        },
-                    ],
-                },
-                {
-                    label: '日本',
-                    value: 'riben',
-                    children: [
-                        {
-                            label: '大阪',
-                            value: 'daban',
-                        },
-                    ],
-                },
-            ],
+          label: '日本',
+          value: 'riben',
+          children: [
+            {
+              label: '大阪',
+              value: 'daban',
+            },
+          ],
         },
-    ];
-    return <Cascader style={{ width: 300, margin: 10 }} treeData={treeData} filterTreeNode />;
+      ],
+    },
+  ];
+  return <Cascader style={{ width: 300, margin: 10 }} treeData={treeData} filterTreeNode />;
 };
 
 const I18nComponent = () => {
-    const [modalVisible, setModalVisible] = useState(false);
-    const style = { margin: 10 };
-    return (
-        <>
-            <Pagination total={100} showTotal showSizeChanger style={style} />
-            <div style={style}>
-                <Button onClick={() => setModalVisible(true)}>Show Modal</Button>
-            </div>
-            <div style={style}>
-                <Select filter style={{ width: '180px' }}>
-                    <Option value="abc">abc</Option>
-                    <Option value="vigo" disabled>
-                        vigo
-                    </Option>
-                    <Option value="hotsoon">hotsoon</Option>
-                </Select>
-                <CascaderDemo />
-            </div>
-            <Modal
-                title="Modal"
-                visible={modalVisible}
-                onOk={() => setModalVisible(false)}
-                onCancel={() => setModalVisible(false)}
-            >
-                <p>This is the content of a basic modal.</p>
-                <p>More content...</p>
-            </Modal>
-            <DatePicker style={{ ...style, width: 200 }} />
-            <DatePicker style={{ ...style, width: 250 }} type="dateTime" />
-            <DatePicker style={{ ...style, width: 250 }} type="dateRange" />
-            <DatePicker style={{ ...style, width: 400 }} type="dateTimeRange" />
-            <TimePicker style={style} />
-            <TimePicker use12Hours style={style} />
-            <br />
-            <br />
-        </>
-    );
+  const [modalVisible, setModalVisible] = useState(false);
+  const style = { margin: 10 };
+  return (
+    <>
+      <Pagination total={100} showTotal showSizeChanger style={style} />
+      <div style={style}>
+        <Button onClick={() => setModalVisible(true)}>Show Modal</Button>
+      </div>
+      <div style={style}>
+        <Select filter style={{ width: '180px' }}>
+          <Option value="abc">abc</Option>
+          <Option value="vigo" disabled>
+            vigo
+          </Option>
+          <Option value="hotsoon">hotsoon</Option>
+        </Select>
+        <CascaderDemo />
+      </div>
+      <Modal
+        title="Modal"
+        visible={modalVisible}
+        onOk={() => setModalVisible(false)}
+        onCancel={() => setModalVisible(false)}
+      >
+        <p>This is the content of a basic modal.</p>
+        <p>More content...</p>
+      </Modal>
+      <DatePicker style={{ ...style, width: 200 }} />
+      <DatePicker style={{ ...style, width: 250 }} type="dateTime" />
+      <DatePicker style={{ ...style, width: 250 }} type="dateRange" />
+      <DatePicker style={{ ...style, width: 400 }} type="dateTimeRange" />
+      <TimePicker style={style} />
+      <TimePicker use12Hours style={style} />
+      <br />
+      <br />
+    </>
+  );
 };
 
 class I18nDemo extends React.Component {
-    constructor(props) {
-        super(props);
-        this.state = {
-            locale: zh_CN,
-        };
-        this.onLanguageChange = this.onLanguageChange.bind(this);
-    }
-
-    onLanguageChange(code) {
-        let language = {
-            zh_CN: zh_CN,
-            en_GB: en_GB,
-            ko_KR: ko_KR,
-            ja_JP: ja_JP,
-        };
-        this.setState({ locale: language[code] });
-    }
-
-    render() {
-        const { locale } = this.state;
-        return (
-            <>
-                <Select onChange={this.onLanguageChange}>
-                    <Option value="zh_CN">中文</Option>
-                    <Option value="en_GB">英语(英)</Option>
-                    <Option value="ja_JP">日语</Option>
-                    <Option value="ko_KR">韩语</Option>
-                </Select>
-                <hr />
-                <LocaleProvider locale={locale}>
-                    <I18nComponent />
-                </LocaleProvider>
-            </>
-        );
-    }
+  constructor(props) {
+    super(props);
+    this.state = {
+      locale: zh_CN,
+    };
+    this.onLanguageChange = this.onLanguageChange.bind(this);
+  }
+
+  onLanguageChange(code) {
+    let language = {
+      zh_CN: zh_CN,
+      en_GB: en_GB,
+      ko_KR: ko_KR,
+      ja_JP: ja_JP,
+    };
+    this.setState({ locale: language[code] });
+  }
+
+  render() {
+    const { locale } = this.state;
+    return (
+      <>
+        <Select onChange={this.onLanguageChange}>
+          <Option value="zh_CN">中文</Option>
+          <Option value="en_GB">英语(英)</Option>
+          <Option value="ja_JP">日语</Option>
+          <Option value="ko_KR">韩语</Option>
+        </Select>
+        <hr />
+        <LocaleProvider locale={locale}>
+          <I18nComponent />
+        </LocaleProvider>
+      </>
+    );
+  }
 }
 
-stories.add('Locale zh_CN', () => (
-    <LocaleProvider locale={zh_CN}>
-        <I18nComponent />
-    </LocaleProvider>
-));
-
-stories.add('Locale en-GB', () => (
-    <LocaleProvider locale={en_GB}>
-        <I18nComponent />
-    </LocaleProvider>
-));
-
-stories.add('Locale en-US', () => (
-    <LocaleProvider locale={en_US}>
-        <I18nComponent />
-    </LocaleProvider>
-));
-
-stories.add('Locale ja_JP', () => (
-    <LocaleProvider locale={ja_JP}>
-        <I18nComponent />
-    </LocaleProvider>
-));
-
-stories.add('Locale ko_KR', () => (
-    <LocaleProvider locale={ko_KR}>
-        <I18nComponent />
-    </LocaleProvider>
-));
-
-stories.add('Locale ru_RU', () => (
-    <LocaleProvider locale={ru_RU}>
-        <I18nComponent />
-    </LocaleProvider>
-));
-
-stories.add('Locale vi_VN', () => (
-    <LocaleProvider locale={vi_VN}>
-        <I18nComponent />
-    </LocaleProvider>
-));
-
-stories.add('Locale', () => <I18nDemo />);
+export const LocaleZhCn = () => (
+  <LocaleProvider locale={zh_CN}>
+    <I18nComponent />
+  </LocaleProvider>
+);
+
+LocaleZhCn.story = {
+  name: 'Locale zh_CN',
+};
+
+export const LocaleEnGb = () => (
+  <LocaleProvider locale={en_GB}>
+    <I18nComponent />
+  </LocaleProvider>
+);
+
+LocaleEnGb.story = {
+  name: 'Locale en-GB',
+};
+
+export const LocaleEnUs = () => (
+  <LocaleProvider locale={en_US}>
+    <I18nComponent />
+  </LocaleProvider>
+);
+
+LocaleEnUs.story = {
+  name: 'Locale en-US',
+};
+
+export const LocaleJaJp = () => (
+  <LocaleProvider locale={ja_JP}>
+    <I18nComponent />
+  </LocaleProvider>
+);
+
+LocaleJaJp.story = {
+  name: 'Locale ja_JP',
+};
+
+export const LocaleKoKr = () => (
+  <LocaleProvider locale={ko_KR}>
+    <I18nComponent />
+  </LocaleProvider>
+);
+
+LocaleKoKr.story = {
+  name: 'Locale ko_KR',
+};
+
+export const LocaleRuRu = () => (
+  <LocaleProvider locale={ru_RU}>
+    <I18nComponent />
+  </LocaleProvider>
+);
+
+LocaleRuRu.story = {
+  name: 'Locale ru_RU',
+};
+
+export const LocaleViVn = () => (
+  <LocaleProvider locale={vi_VN}>
+    <I18nComponent />
+  </LocaleProvider>
+);
+
+LocaleViVn.story = {
+  name: 'Locale vi_VN',
+};
+
+export const Locale = () => <I18nDemo />;

+ 1 - 1
packages/semi-ui/modal/_story/CollapsibleInModal/index.jsx

@@ -97,4 +97,4 @@ class Demo extends React.Component {
         );
     }
 }
-export default Demo;
+export default () => <Demo />;

+ 201 - 152
packages/semi-ui/modal/_story/modal.stories.js

@@ -1,202 +1,251 @@
 import React, { useState } from 'react';
-import { storiesOf } from '@storybook/react';
 import { Select, Modal, Button, Tooltip, Popover } from '../../index';
 import CollapsibleInModal from './CollapsibleInModal';
 import DynamicContextDemo from './DynamicContext';
 
-const stories = storiesOf('Modal', module);
+export default {
+  title: 'Modal',
+  parameters: {
+    chromatic: { disableSnapshot: true },
+  },
+}
+
+export {
+  CollapsibleInModal,
+  DynamicContextDemo
+}
 
 const Option = Select.Option;
 
 const DialogComponent = props => {
-    const [visible, setVisible] = useState(false);
-
-    const handleOk = e => {
-        setVisible(false);
-    };
-
-    const handleCancel = e => {
-        setVisible(false);
-    };
-
-    return (
-        <React.Fragment>
-            <Button onClick={() => setVisible(true)}>show dialog</Button>
-            <Modal title="对话框标题" visible={visible} onOk={handleOk} onCancel={handleCancel} {...props}>
-                <input autoFocus />
-                <p>basic modal</p>
-                <Button onClick={handleCancel}>hide dialog</Button>
-            </Modal>
-        </React.Fragment>
-    );
+  const [visible, setVisible] = useState(false);
+
+  const handleOk = e => {
+    setVisible(false);
+  };
+
+  const handleCancel = e => {
+    setVisible(false);
+  };
+
+  return (
+    <React.Fragment>
+      <Button onClick={() => setVisible(true)}>show dialog</Button>
+      <Modal
+        title="对话框标题"
+        visible={visible}
+        onOk={handleOk}
+        onCancel={handleCancel}
+        {...props}
+      >
+        <input autoFocus />
+        <p>basic modal</p>
+        <Button onClick={handleCancel}>hide dialog</Button>
+      </Modal>
+    </React.Fragment>
+  );
+};
+
+export const Default = () => <DialogComponent />;
+
+Default.story = {
+  name: 'default',
 };
 
-stories.add('模态框默认', () => <DialogComponent />);
+export const ClickMaskClosableFalse = () => <DialogComponent maskClosable={false} />;
 
-stories.add('模态框-点击遮罩层不可关闭', () => <DialogComponent maskClosable={false} />);
+ClickMaskClosableFalse.story = {
+  name: 'click mask closable false',
+};
 
 function useLoading() {
-    const [loading, setLoading] = useState(false);
-    function startQuery() {
-        setLoading(true);
-    }
-    return [loading, { startQuery }];
+  const [loading, setLoading] = useState(false);
+  function startQuery() {
+    setLoading(true);
+  }
+  return [loading, { startQuery }];
 }
 
 function DialogComponentWithLoading() {
-    const [loading, actions] = useLoading();
-    return <DialogComponent confirmLoading={loading} onOk={actions.startQuery} />;
+  const [loading, actions] = useLoading();
+  return <DialogComponent confirmLoading={loading} onOk={actions.startQuery} />;
 }
 
-// button 组件的 loading ui还没有实现
-stories.add('模态框-点击确认按钮展现loading, button组件的loading没有实现,所以现在还没有', () => (
-    <DialogComponentWithLoading />
-));
+export const WithLoadingTodo = () => <DialogComponentWithLoading />;
+
+WithLoadingTodo.story = {
+  name: 'with loading todo',
+};
 
 function success() {
-    Modal.success('bla bla bla...');
+  Modal.success('bla bla bla...');
 }
 
 function info() {
-    Modal.info('info');
+  Modal.info('info');
 }
 
 function error() {
-    Modal.error({ title: 'Unfortunately, there is an error', content: 'bla bla bla...' });
+  Modal.error({ title: 'Unfortunately, there is an error', content: 'bla bla bla...' });
 }
 
 function warning() {
-    Modal.warning({ title: 'Warning: be cautious ahead', content: 'bla bla bla...' });
+  Modal.warning({ title: 'Warning: be cautious ahead', content: 'bla bla bla...' });
 }
 
 function confirm() {
-    Modal.confirm({ title: 'Are you sure ?', content: 'bla bla bla...' });
+  Modal.confirm({ title: 'Are you sure ?', content: 'bla bla bla...' });
 }
 
-stories.add('命令式调用', () => (
-    <div>
-        <Button onClick={info}>Info</Button>
-        <Button onClick={success}>Success</Button>
-        <Button onClick={error}>Error</Button>
-        <Button onClick={warning}>Warning</Button>
-        <Button onClick={confirm}>Confirm</Button>
-    </div>
-));
+export const ConfirmModal = () => (
+  <div>
+    <Button onClick={info}>Info</Button>
+    <Button onClick={success}>Success</Button>
+    <Button onClick={error}>Error</Button>
+    <Button onClick={warning}>Warning</Button>
+    <Button onClick={confirm}>Confirm</Button>
+  </div>
+);
+
+ConfirmModal.story = {
+  name: 'confirm modal',
+};
 
 const Test = () => {
-    let modal;
-
-    const showModal = () => {
-        modal = Modal.info({
-            title: '修改的标题',
-            content: (
-                <>
-                    <Button onClick={() => modal && modal.destroy()}>close</Button>
-                    <Button onClick={() => modal && modal.update({ title: 'lalala updating' })}>update</Button>
-                </>
-            ),
-        });
-    };
-
-    return <Button onClick={() => showModal()}>Info</Button>;
+  let modal;
+
+  const showModal = () => {
+    modal = Modal.info({
+      title: '修改的标题',
+      content: (
+        <>
+          <Button onClick={() => modal && modal.destroy()}>close</Button>
+          <Button onClick={() => modal && modal.update({ title: 'lalala updating' })}>
+            update
+          </Button>
+        </>
+      ),
+    });
+  };
+
+  return <Button onClick={() => showModal()}>Info</Button>;
 };
 
-stories.add('modal.destroy', () => <Test />);
+export const ModalDestroy = () => <Test />;
+
+ModalDestroy.story = {
+  name: 'modal.destroy',
+};
 
 const ScrollComponent = props => {
-    const [visible, setVisible] = useState(true);
-
-    const handleOk = e => {
-        setVisible(false);
-    };
-
-    const handleCancel = e => {
-        setVisible(false);
-    };
-
-    return (
-        <div style={{ paddingTop: 900, paddingBotttom: 800 }}>
-            <Button onClick={() => setVisible(true)}>show dialog</Button>
-            <Modal
-                id="modal-test"
-                title="对话框标题"
-                visible={visible}
-                onOk={handleOk}
-                onCancel={handleCancel}
-                {...props}
-            >
-                <Select>
-                    <Option value={1}>opt1</Option>
-                    <Option value={2}>opt2</Option>
-                    <Option value={3}>opt3</Option>
-                    <Option value={4}>opt4</Option>
-                    <Option value={5}>opt5</Option>
-                    <Option value={6}>opt6</Option>
-                </Select>
-                <Tooltip content="fefefefeef">test tooltip in modal</Tooltip>
-                <Button onClick={handleCancel}>hide dialog</Button>
-                <Popover content={'1,2,3'}>
-                    <Button>hover</Button>
-                </Popover>
-            </Modal>
-            <Select>
-                <Option value={1}>opt1</Option>
-                <Option value={2}>opt2</Option>
-                <Option value={3}>opt3</Option>
-                <Option value={4}>opt4</Option>
-                <Option value={5}>opt5</Option>
-                <Option value={6}>opt6</Option>
-            </Select>
-        </div>
-    );
+  const [visible, setVisible] = useState(true);
+
+  const handleOk = e => {
+    setVisible(false);
+  };
+
+  const handleCancel = e => {
+    setVisible(false);
+  };
+
+  return (
+    <div style={{ paddingTop: 900, paddingBotttom: 800 }}>
+      <Button onClick={() => setVisible(true)}>show dialog</Button>
+      <Modal
+        id="modal-test"
+        title="对话框标题"
+        visible={visible}
+        onOk={handleOk}
+        onCancel={handleCancel}
+        {...props}
+      >
+        <Select>
+          <Option value={1}>opt1</Option>
+          <Option value={2}>opt2</Option>
+          <Option value={3}>opt3</Option>
+          <Option value={4}>opt4</Option>
+          <Option value={5}>opt5</Option>
+          <Option value={6}>opt6</Option>
+        </Select>
+        <Tooltip content="fefefefeef">test tooltip in modal</Tooltip>
+        <Button onClick={handleCancel}>hide dialog</Button>
+        <Popover content={'1,2,3'}>
+          <Button>hover</Button>
+        </Popover>
+      </Modal>
+      <Select>
+        <Option value={1}>opt1</Option>
+        <Option value={2}>opt2</Option>
+        <Option value={3}>opt3</Option>
+        <Option value={4}>opt4</Option>
+        <Option value={5}>opt5</Option>
+        <Option value={6}>opt6</Option>
+      </Select>
+    </div>
+  );
 };
 
-stories.add('滚动', () => <ScrollComponent />);
+export const Scroll = () => <ScrollComponent />;
+
+Scroll.story = {
+  name: 'scroll',
+};
 
 const Popup = () => {
-    const [visible, setVisible] = useState(false);
-    const getContainer = () => {
-        return document.querySelector('.modal-container');
-    };
-    return (
-        <div
-            style={{
-                height: 320,
-                overflow: 'hidden',
-                position: 'relative',
-                border: '1px solid var(--semi-color-border)',
-                borderRadius: 2,
-                padding: 24,
-                textAlign: 'center',
-                background: 'var(--semi-color-fill-0)',
-            }}
-            className="modal-container"
-        >
-            <span>Render in this</span>
-            <br />
-            <br />
-            <Button onClick={() => setVisible(true)}>Open Modal</Button>
-            <Modal
-                title="渲染在指定容器内部"
-                visible={visible}
-                onCancel={() => setVisible(false)}
-                width={200}
-                // centered
-                // style={{ top: '10px' }}
-                getPopupContainer={getContainer}
-            >
-                <p>This is the content of a basic sidesheet.</p>
-                <p>Here is more content...</p>
-            </Modal>
-        </div>
-    );
+  const [visible, setVisible] = useState(false);
+  const getContainer = () => {
+    return document.querySelector('.modal-container');
+  };
+  return (
+    <div
+      style={{
+        height: 320,
+        overflow: 'hidden',
+        position: 'relative',
+        border: '1px solid var(--semi-color-border)',
+        borderRadius: 2,
+        padding: 24,
+        textAlign: 'center',
+        background: 'var(--semi-color-fill-0)',
+      }}
+      className="modal-container"
+    >
+      <span>Render in this</span>
+      <br />
+      <br />
+      <Button onClick={() => setVisible(true)}>Open Modal</Button>
+      <Modal
+        title="渲染在指定容器内部"
+        visible={visible}
+        onCancel={() => setVisible(false)}
+        width={200}
+        // centered
+        // style={{ top: '10px' }}
+        getPopupContainer={getContainer}
+      >
+        <p>This is the content of a basic sidesheet.</p>
+        <p>Here is more content...</p>
+      </Modal>
+    </div>
+  );
+};
+
+export const RenderInCustomContainer = () => <Popup />;
+
+RenderInCustomContainer.story = {
+  name: 'render in custom container',
+};
+
+export const KeepDom = () => <DialogComponent keepDOM />;
+
+KeepDom.story = {
+  name: 'keepDOM',
 };
 
-stories.add('渲染在指定容器内部', () => <Popup />);
+export const KeepDomNotLazy = () => <DialogComponent keepDOM lazyRender={false} />;
 
-stories.add(`dynamic context demo`, () => <DynamicContextDemo />);
-stories.add(`collapsible in modal`, () => <CollapsibleInModal />);
+KeepDomNotLazy.story = {
+  name: 'keepDOM && not lazy',
+};
 
-stories.add('keepDOM', () => <DialogComponent keepDOM />);
 
-stories.add('keepDOM && not lazy', () => <DialogComponent keepDOM lazyRender={false} />);

+ 286 - 218
packages/semi-ui/navigation/_story/navigation.stories.js

@@ -1,5 +1,4 @@
 import React from 'react';
-import { storiesOf } from '@storybook/react';
 
 import Nav from '..';
 import Switch from '../../switch';
@@ -13,250 +12,319 @@ import ItemsChange from './ItemsChange';
 import DisabledNav from './DisabledNav';
 import Button from '../../button';
 
-import { IconMail, IconFolder, IconGift, IconList,
-     IconFlag, IconStar, IconCloud, IconEdit,
-     IconFile,IconCamera,IconArticle,IconUser,IconAscend,IconDescend,IconSetting,IconUserGroup } from '@douyinfe/semi-icons';
+import {
+  IconMail,
+  IconFolder,
+  IconGift,
+  IconList,
+  IconFlag,
+  IconStar,
+  IconCloud,
+  IconEdit,
+  IconFile,
+  IconCamera,
+  IconArticle,
+  IconUser,
+  IconAscend,
+  IconDescend,
+  IconSetting,
+  IconUserGroup,
+} from '@douyinfe/semi-icons';
 
-const stories = storiesOf('Navigation', module);
+export default {
+  title: 'Navigation'
+}
+
+export const Default = () => {
+  return (
+    <div style={{ height: '100vh', display: 'inline-block' }}>
+      <Nav onSelect={(...args) => console.log(...args)}>
+        <Nav.Item itemKey={'1'} text={'Option 1'} icon={<IconMail />} />
+        <Nav.Sub text={'Group 2'} icon={<IconFolder />} stayWhenClick={true} itemKey={'2'}>
+          {['2-1', '2-2'].map(k => (
+            <Nav.Item key={k} itemKey={String(k)} text={'Option ' + k} />
+          ))}
+          <Nav.Item itemKey={'2-3'} text={'Option 2-3'} />
+          <Nav.Sub text={'Group 2-4'} itemKey={'2-4'}>
+            <Nav.Item itemKey={'2-4-1'} text={'Option 2-3-1'} />
+            <Nav.Item itemKey={'2-4-2'} text={'Option 2-3-2'} />
+          </Nav.Sub>
+        </Nav.Sub>
+        <Nav.Item key={3} itemKey={'3'} text={'Option 3'} icon={<IconGift />} />
+        <Nav.Item key={4} itemKey={'4'} text={'Option 4'} icon={<IconList />} />
+        <Nav.Sub text={'Group 5'} icon={<IconFlag />} stayWhenClick={true} itemKey={'5'}>
+          {['5-1', '5-2'].map(k => (
+            <Nav.Item key={k} itemKey={String(k)} text={'Option ' + k} />
+          ))}
+        </Nav.Sub>
+        <Nav.Item itemKey={'6'} text={'Option 6 (with link)'} icon={<IconStar />} link="/star" />
+        <Nav.Sub text={'Group 7'} icon={<IconFolder />} stayWhenClick={true} itemKey={'7'}>
+          {['7-1', '7-2'].map(k => (
+            <Nav.Item
+              key={k}
+              itemKey={String(k)}
+              text={'Option ' + k + ' (with link)'}
+              link={`folder/${k}`}
+            />
+          ))}
+          <Nav.Item itemKey={'7-3'} text={'Option 7-3'} />
+        </Nav.Sub>
+      </Nav>
+    </div>
+  );
+};
 
-// stories.addDecorator(withKnobs);;
+Default.story = {
+  name: 'default',
+};
+
+class NavApp extends React.Component {
+  state = {
+    isCollapsed: true,
+  };
 
-stories.add('普通导航', () => {
+  updateCollapsed = isCollapsed => {
+    this.setState({ isCollapsed });
+  };
+
+  render() {
+    let { isCollapsed } = this.state;
     return (
-        <div style={{ height: '100vh', display: 'inline-block' }}>
-            <Nav onSelect={(...args) => console.log(...args)}>
-                <Nav.Item itemKey={'1'} text={'Option 1'} icon={<IconMail />} />
-                <Nav.Sub text={'Group 2'} icon={<IconFolder />} stayWhenClick={true} itemKey={'2'}>
-                    {['2-1', '2-2'].map(k => (
-                        <Nav.Item key={k} itemKey={String(k)} text={'Option ' + k} />
-                    ))}
-                    <Nav.Item itemKey={'2-3'} text={'Option 2-3'} />
-                    <Nav.Sub text={'Group 2-4'} itemKey={'2-4'}>
-                        <Nav.Item itemKey={'2-4-1'} text={'Option 2-3-1'} />
-                        <Nav.Item itemKey={'2-4-2'} text={'Option 2-3-2'} />
-                    </Nav.Sub>
-                </Nav.Sub>
-                <Nav.Item key={3} itemKey={'3'} text={'Option 3'} icon={<IconGift />} />
-                <Nav.Item key={4} itemKey={'4'} text={'Option 4'} icon={<IconList />} />
-                <Nav.Sub text={'Group 5'} icon={<IconFlag />} stayWhenClick={true} itemKey={'5'}>
-                    {['5-1', '5-2'].map(k => (
-                        <Nav.Item key={k} itemKey={String(k)} text={'Option ' + k} />
-                    ))}
-                </Nav.Sub>
-                <Nav.Item itemKey={'6'} text={'Option 6 (with link)'} icon={<IconStar />} link="/star" />
-                <Nav.Sub text={'Group 7'} icon={<IconFolder />} stayWhenClick={true} itemKey={'7'}>
-                    {['7-1', '7-2'].map(k => (
-                        <Nav.Item key={k} itemKey={String(k)} text={'Option ' + k + ' (with link)'} link={`folder/${k}`} />
-                    ))}
-                    <Nav.Item itemKey={'7-3'} text={'Option 7-3'} />
-                </Nav.Sub>
-            </Nav>
+      <div style={{ height: '100vh', display: 'inline-block' }}>
+        <div>
+          {'收起到左侧'}
+          <Switch defaultChecked={isCollapsed} onChange={v => this.updateCollapsed(v)} />
         </div>
+        <Nav isCollapsed={isCollapsed}>
+          <Nav.Item itemKey={'1'} text={'Option 1'} icon={<IconCloud />} />
+          <Nav.Sub text={'Group 2'} icon={<IconEdit />} stayWhenClick={true}>
+            {['2-1', '2-2'].map(k => (
+              <Nav.Item key={k} itemKey={String(k)} text={'Option ' + k} />
+            ))}
+            <Nav.Sub text={'Group 2-3'} icon={<IconFile />}>
+              <Nav.Item itemKey={'2-3-1'} text={'Option 2-3-1'} />
+              <Nav.Item itemKey={'2-3-2'} text={'Option 2-3-2'} />
+            </Nav.Sub>
+          </Nav.Sub>
+          <Nav.Item key={3} itemKey={'3'} text={'Option 3'} icon={<IconCamera />} />
+          <Nav.Item key={4} itemKey={'4'} text={'Option 4'} icon={<IconArticle />} />
+          <Nav.Sub text={'Group 5'} stayWhenClick={true} icon={<IconFolder />}>
+            {['5-1', '5-2'].map(k => (
+              <Nav.Item key={k} itemKey={String(k)} text={'Option ' + k} />
+            ))}
+          </Nav.Sub>
+        </Nav>
+      </div>
     );
-});
+  }
+}
 
-class NavApp extends React.Component {
-    state = {
-        isCollapsed: true,
-    };
+export const CollapseExpand = () => <NavApp />;
 
-    updateCollapsed = isCollapsed => {
-        this.setState({ isCollapsed });
-    };
+CollapseExpand.story = {
+  name: 'collapse/expand',
+};
 
-    render() {
-        let { isCollapsed } = this.state;
-        return (
-            <div style={{ height: '100vh', display: 'inline-block' }}>
-                <div>
-                    {'收起到左侧'}
-                    <Switch defaultChecked={isCollapsed} onChange={v => this.updateCollapsed(v)} />
-                </div>
-                <Nav isCollapsed={isCollapsed}>
-                    <Nav.Item itemKey={'1'} text={'Option 1'} icon={<IconCloud />} />
-                    <Nav.Sub text={'Group 2'} icon={<IconEdit />} stayWhenClick={true}>
-                        {['2-1', '2-2'].map(k => (
-                            <Nav.Item key={k} itemKey={String(k)} text={'Option ' + k} />
-                        ))}
-                        <Nav.Sub text={'Group 2-3'} icon={<IconFile />}>
-                            <Nav.Item itemKey={'2-3-1'} text={'Option 2-3-1'} />
-                            <Nav.Item itemKey={'2-3-2'} text={'Option 2-3-2'} />
-                        </Nav.Sub>
-                    </Nav.Sub>
-                    <Nav.Item key={3} itemKey={'3'} text={'Option 3'} icon={<IconCamera />} />
-                    <Nav.Item key={4} itemKey={'4'} text={'Option 4'} icon={<IconArticle />} />
-                    <Nav.Sub text={'Group 5'} stayWhenClick={true} icon={<IconFolder />}>
-                        {['5-1', '5-2'].map(k => (
-                            <Nav.Item key={k} itemKey={String(k)} text={'Option ' + k} />
-                        ))}
-                    </Nav.Sub>
-                </Nav>
-            </div>
-        );
-    }
-}
+export const ConfigItems = () => (
+  <div style={{ border: '1px solid black', height: '100vh', display: 'inline-block' }}>
+    <Nav
+      items={[
+        { itemKey: 'user', text: '用户管理', icon: <IconUser />, link: '/user' },
+        { itemKey: 'union', text: '公会中心', icon: <IconUser />, link: '/star' },
+        {
+          text: '任务平台',
+          icon: <IconSetting />,
+          itemKey: 'job',
+          items: ['任务管理', '用户任务查询'],
+        },
+      ]}
+      onSelect={key => console.log(key)}
+    />
+  </div>
+);
 
-stories.add('收起/展开导航', () => <NavApp />);
+ConfigItems.story = {
+  name: 'config items',
+};
 
-stories.add('基于配置渲染的导航', () => (
-    <div style={{ border: '1px solid black', height: '100vh', display: 'inline-block' }}>
-        <Nav
-            items={[
-                { itemKey: 'user', text: '用户管理', icon: <IconUser />, link: '/user' },
-                { itemKey: 'union', text: '公会中心', icon: <IconUser />, link: '/star' },
-                {
-                    text: '任务平台',
-                    icon: <IconSetting />,
-                    itemKey: 'job',
-                    items: ['任务管理', '用户任务查询'],
-                },
-            ]}
-            onSelect={key => console.log(key)}
-        />
-    </div>
-));
+export const Horizontal = () => (
+  <div>
+    <Nav
+      mode="horizontal"
+      items={[
+        '1',
+        { itemKey: '2', text: 'Option 2 Option 2 Option 2 Option 2', icon: <IconCamera /> },
+        {
+          text: 'Group 3',
+          itemKey: '3',
+          icon: <IconFile />,
+          items: ['3-1', '3-2', { text: 'Group 3-3', items: ['3-3-1', '3-3-2'] }],
+        },
+      ]}
+      onSelect={key => console.log(key)}
+    />
+  </div>
+);
 
-stories.add('横向导航', () => (
-    <div>
-        <Nav
-            mode="horizontal"
-            items={[
-                '1',
-                { itemKey: '2', text: 'Option 2 Option 2 Option 2 Option 2', icon: <IconCamera /> },
-                {
-                    text: 'Group 3',
-                    itemKey: '3',
-                    icon: <IconFile />,
-                    items: ['3-1', '3-2', { text: 'Group 3-3', items: ['3-3-1', '3-3-2'] }],
-                },
-            ]}
-            onSelect={key => console.log(key)}
-        />
-    </div>
-));
+Horizontal.story = {
+  name: 'horizontal',
+};
 
 class Demo extends React.Component {
-    constructor() {
-        super();
-        this.state = {
-            isCollapsed: false,
-            defaultOpenKeys: ['2', '2-3'],
-            mode: 'vertical',
-            navHeight: '100vh',
-        };
-    }
+  constructor() {
+    super();
+    this.state = {
+      isCollapsed: false,
+      defaultOpenKeys: ['2', '2-3'],
+      mode: 'vertical',
+      navHeight: '100vh',
+    };
+  }
 
-    updateCollapsed(isCollapsed) {
-        this.setState({ isCollapsed });
-    }
+  updateCollapsed(isCollapsed) {
+    this.setState({ isCollapsed });
+  }
 
-    render() {
-        let { isCollapsed, defaultOpenKeys, mode, navHeight } = this.state;
-        let logo = '//lf1-cdn-tos.bytescm.com/obj/ttfe/ies/semi/logo_huoshan.png';
-        let testIcon = '//lf1-cdn-tos.bytescm.com/obj/mosaic-legacy/da9d0015af0f09667998';
-        let vigoIcon = '//lf1-cdn-tos.bytescm.com/obj/mosaic-legacy/504100070cbe0498d66f';
-        return (
-            <div>
-                <Nav
-                    isCollapsed={isCollapsed}
-                    defaultOpenKeys={defaultOpenKeys}
-                    style={{ height: navHeight }}
-                    mode={mode}
-                >
-                    <Nav.Header logo={<img src={logo} />} text="互娱运营" />
-                    <Nav.Item
-                        itemKey={'1'}
-                        text={<strong>火山运营</strong>}
-                        icon={<img width="20" height="20" src={vigoIcon} />}
-                    />
-                    <Nav.Sub
-                        itemKey={'2'}
-                        text={<span>抖音运营</span>}
-                        icon={<img width="20" height="20" src={testIcon} />}
-                        stayWhenClick={true}
-                    >
-                        {['2-1', '2-2'].map(k => (
-                            <Nav.Item key={k} itemKey={String(k)} text={'Option ' + k} />
-                        ))}
-                    </Nav.Sub>
-                    <Nav.Footer>
-                        <Button
-                            title="展开/收起切换"
-                            icon={isCollapsed ? <IconAscend /> : <IconDescend />}
-                            onClick={() => this.updateCollapsed(!isCollapsed)}
-                        />
-                    </Nav.Footer>
-                </Nav>
-            </div>
-        );
-    }
+  render() {
+    let { isCollapsed, defaultOpenKeys, mode, navHeight } = this.state;
+    let logo = '//lf1-cdn-tos.bytescm.com/obj/ttfe/ies/semi/logo_huoshan.png';
+    let testIcon = '//lf1-cdn-tos.bytescm.com/obj/mosaic-legacy/da9d0015af0f09667998';
+    let vigoIcon = '//lf1-cdn-tos.bytescm.com/obj/mosaic-legacy/504100070cbe0498d66f';
+    return (
+      <div>
+        <Nav
+          isCollapsed={isCollapsed}
+          defaultOpenKeys={defaultOpenKeys}
+          style={{ height: navHeight }}
+          mode={mode}
+        >
+          <Nav.Header logo={<img src={logo} />} text="互娱运营" />
+          <Nav.Item
+            itemKey={'1'}
+            text={<strong>火山运营</strong>}
+            icon={<img width="20" height="20" src={vigoIcon} />}
+          />
+          <Nav.Sub
+            itemKey={'2'}
+            text={<span>抖音运营</span>}
+            icon={<img width="20" height="20" src={testIcon} />}
+            stayWhenClick={true}
+          >
+            {['2-1', '2-2'].map(k => (
+              <Nav.Item key={k} itemKey={String(k)} text={'Option ' + k} />
+            ))}
+          </Nav.Sub>
+          <Nav.Footer>
+            <Button
+              title="展开/收起切换"
+              icon={isCollapsed ? <IconAscend /> : <IconDescend />}
+              onClick={() => this.updateCollapsed(!isCollapsed)}
+            />
+          </Nav.Footer>
+        </Nav>
+      </div>
+    );
+  }
 }
-stories.add('配logo,展开/收起切换', () => <Demo />);
+export const ExpandCollapseWithLogo = () => <Demo />;
+
+ExpandCollapseWithLogo.story = {
+  name: 'expand collapse with logo',
+};
 
 class HorizontalDemo extends React.Component {
-    render() {
-        return (
-            <div style={{ width: '100%' }}>
-                <Nav
-                    bodyStyle={{ height: 320 }}
-                    items={[
-                        { itemKey: 'user', text: '用户管理', icon: <IconUser /> },
-                        { itemKey: 'union', text: '公会中心', icon: <IconStar /> },
-                        {
-                            itemKey: 'union-management',
-                            text: '公会管理',
-                            icon: <IconUserGroup />,
-                            items: ['公告设置', '公会查询', '信息录入'],
-                        },
-                        {
-                            itemKey: 'approve-management',
-                            text: '审批管理',
-                            icon: <IconEdit />,
-                            items: [
-                                '入驻审核',
-                                {
-                                    itemKey: 'operation-management',
-                                    text: '运营管理',
-                                    items: ['人员管理', '人员变更'],
-                                },
-                            ],
-                        },
-                        {
-                            text: '任务平台',
-                            icon: <IconSetting />,
-                            itemKey: 'job',
-                            items: ['任务管理', '用户任务查询'],
-                        },
-                    ]}
-                    onSelect={key => console.log(key)}
-                    header={{
-                        logo: <img src="https://sf6-cdn-tos.douyinstatic.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/webcast_logo.svg" />,
-                        text: '直播运营后台',
-                    }}
-                    footer={{
-                        collapseButton: true,
-                    }}
-                />
-            </div>
-        );
-    }
+  render() {
+    return (
+      <div style={{ width: '100%' }}>
+        <Nav
+          bodyStyle={{ height: 320 }}
+          items={[
+            { itemKey: 'user', text: '用户管理', icon: <IconUser /> },
+            { itemKey: 'union', text: '公会中心', icon: <IconStar /> },
+            {
+              itemKey: 'union-management',
+              text: '公会管理',
+              icon: <IconUserGroup />,
+              items: ['公告设置', '公会查询', '信息录入'],
+            },
+            {
+              itemKey: 'approve-management',
+              text: '审批管理',
+              icon: <IconEdit />,
+              items: [
+                '入驻审核',
+                {
+                  itemKey: 'operation-management',
+                  text: '运营管理',
+                  items: ['人员管理', '人员变更'],
+                },
+              ],
+            },
+            {
+              text: '任务平台',
+              icon: <IconSetting />,
+              itemKey: 'job',
+              items: ['任务管理', '用户任务查询'],
+            },
+          ]}
+          onSelect={key => console.log(key)}
+          header={{
+            logo: (
+              <img src="https://sf6-cdn-tos.douyinstatic.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/webcast_logo.svg" />
+            ),
+            text: '直播运营后台',
+          }}
+          footer={{
+            collapseButton: true,
+          }}
+        />
+      </div>
+    );
+  }
 }
-stories.add('配logo,横向导航栏', () => <HorizontalDemo />);
+export const HorizontalWithLogo = () => <HorizontalDemo />;
 
-stories.add('auto open', () => <AutoOpenDemo />);
+HorizontalWithLogo.story = {
+  name: 'horizontal with logo',
+};
 
-stories.add(`link nav`, () => <LinkNavDemo />);
+export const AutoOpen = () => <AutoOpenDemo />;
 
-stories.add(`mount unmount`, () => <MountUnmount />);
+AutoOpen.story = {
+  name: 'auto open',
+};
 
-stories.add(`controlled selected keys`, () => <ControlledSelectedKeys />);
+export const LinkNav = () => <LinkNavDemo />;
+LinkNav.story = {
+  name: 'link nav',
+}
 
-stories.add(`with router`, () => <WithRouter />);
+export const MountUnmountDemo = () => <MountUnmount />;
+MountUnmountDemo.story = {
+  name: 'mount unmount'
+}
 
-stories.add(`with children`, () => <WithChildren />);
+export const ControlledSelectedKeysDemo = () => <ControlledSelectedKeys />;
+ControlledSelectedKeysDemo.story = {
+  name: 'controlled selected keys'
+};
 
-stories.add(`nav cannot set item to 0 dynaicly`, () => <ItemsChange />);
+export const WithRouterDemo = () => <WithRouter />;
+WithRouter.story = {
+  name: 'with router'
+};
 
-stories.add(`disabled nav`, () => <DisabledNav />);
+export const WithChildrenDemo = () => <WithChildren />;
+WithChildrenDemo.story = {
+  name: 'with children'
+}
 
+export const ItemsChangeDemo = () => <ItemsChange />;
+ItemsChangeDemo.story = {
+  name: 'nav cannot set item to 0 dynamically'
+};
 
+export const DisabledNavDemo = () => <DisabledNav />;
+DisabledNavDemo.story = {
+  name: 'disabled nav'
+}

+ 195 - 162
packages/semi-ui/notification/_story/notification.stories.js

@@ -1,192 +1,225 @@
 import React from 'react';
-import { storiesOf } from '@storybook/react';
-// import { withKnobs, text, boolean } from '@storybook/addon-knobs';
-import withPropsCombinations from 'react-storybook-addon-props-combinations';
-import {IconWifi, IconToutiaoLogo} from '@douyinfe/semi-icons';
 
+import { IconWifi, IconToutiaoLogo } from '@douyinfe/semi-icons';
 import Notification from '../index';
-
 import Button from '@douyinfe/semi-ui/button/index';
-
 import UseNotificationDemo from './useNotification';
 
-const stories = storiesOf('Notification', module);
+export default {
+  title: 'Notification',
+  parameters: {
+    chromatic: { disableSnapshot: true },
+  },
+}
 
-// stories.addDecorator(withKnobs);;
 
 let noticeIds = [];
 const fnc = () => {
-    let id = Notification.info({ content: '0', duration: 0 });
-    noticeIds.push(id);
+  let id = Notification.info({ content: '0', duration: 0 });
+  noticeIds.push(id);
 };
 
 const remove = () => {
-    let id = noticeIds[0];
-    console.log(noticeIds);
-    Notification.close(id);
-    noticeIds = noticeIds.filter(key => id !== key);
+  let id = noticeIds[0];
+  console.log(noticeIds);
+  Notification.close(id);
+  noticeIds = noticeIds.filter(key => id !== key);
 };
 
 let pos = ['topRight', 'topLeft', 'bottomRight', 'bottomLeft'];
 let opts = {
-    title: 'Title ies',
-    content: 'Hi,Bytedance dance dance dance dance dance dance dance dance dance dance dance dance dance dance dance',
-    duration: 3,
+  title: 'Title ies',
+  content:
+    'Hi,Bytedance dance dance dance dance dance dance dance dance dance dance dance dance dance dance dance',
+  duration: 3,
 };
 
 function randomPos() {
-    return pos[Math.floor(Math.random() * pos.length)];
+  return pos[Math.floor(Math.random() * pos.length)];
 }
-stories.add('notification', () => (
-    <div>
-        <Button
-            type="primary"
-            onClick={() => Notification.info({ ...opts, content: '我三秒后会被关闭', position: randomPos() })}
-        >
-            After 3s
-        </Button>
-        <Button type="primary" onClick={() => Notification.open({ ...opts, duration: 2, position: 'topRight' })}>
-            After 2s
-        </Button>
-    </div>
-));
-
-stories.add('manaul open & close', () => (
-    <div>
-        <Button type="primary" onClick={fnc}>
-            Duration:0
-        </Button>
-        <Button type="primary" onClick={remove}>
-            remove duration:
-        </Button>
-    </div>
-));
-
-stories.add('不同位置', () => {
-    let opts = {
-        duration: 0,
-        position: 'topRight',
-        content: 'semi-ui-notification',
-        title: 'Hi bytedance',
-    };
-    return (
-        <>
-            <Button onClick={() => Notification.info({ ...opts, position: 'top' })}>top</Button>
-            <Button onClick={() => Notification.info({ ...opts, position: 'topLeft' })}>topLeft</Button>
-            <Button onClick={() => Notification.info(opts)}>topRight</Button>
-            <Button onClick={() => Notification.info({ ...opts, position: 'bottom' })}>bottom</Button>
-            <Button onClick={() => Notification.info({ ...opts, position: 'bottomRight' })}>bottomRight</Button>
-            <Button onClick={() => Notification.info({ ...opts, position: 'bottomLeft' })}>bottomLeft</Button>
-        </>
-    );
-});
-
-stories.add('自定义icon', () => {
-    let opts = {
-        duration: 0,
-        position: 'topRight',
-        content: 'semi-ui-notification',
-        title: 'Hi bytedance',
-    };
-    return (
-        <>
-            <Button onClick={() => Notification.info({ ...opts, position: 'top' })}>info</Button>
-            <Button onClick={() => Notification.warning({ ...opts, position: 'top' })}>warning</Button>
-            <Button
-                onClick={() =>
-                    Notification.info({ ...opts, position: 'top', icon: <IconWifi style={{color: 'green'}} /> })
-                }
-            >
-                wifi
-            </Button>
-            <Button
-                onClick={() =>
-                    Notification.info({
-                        ...opts,
-                        position: 'bottomLeft',
-                        icon: <IconToutiaoLogo style={{ color: 'red' }} />,
-                    })
-                }
-            >
-                toutiao
-            </Button>
-        </>
-    );
-});
-
-stories.add('事件', () => {
-    let opts = {
-        duration: 0,
-        position: 'topRight',
-        content: 'semi-ui-notification',
-        title: 'Hi bytedance',
-        onClick: e => console.log('clicking'),
-        onClose: e => console.log('closing da da da...'),
-        onCloseClick: e => console.log('you closed me'),
-    };
-    return (
-        <>
-            <Button onClick={() => Notification.info({ ...opts, position: 'top' })}>info</Button>
-            <Button onClick={() => Notification.warning({ ...opts, position: 'top' })}>warning</Button>
-            <Button
-                onClick={() =>
-                    Notification.info({ ...opts, position: 'top', icon: <IconWifi style={{color: 'green'}} /> })
-                }
-            >
-                wifi
-            </Button>
-            <Button
-                onClick={() =>
-                    Notification.info({
-                        ...opts,
-                        position: 'bottomLeft',
-                        icon: <IconToutiaoLogo style={{ color: 'red' }} />,
-                    })
-                }
-            >
-                toutiao
-            </Button>
-        </>
-    );
-});
 
-class Demo extends React.Component {
-    constructor() {
-        super();
-        this.state = { test: 0 };
-        this.onClick = this.onClick.bind(this);
-    }
+export const _Notification = () => (
+  <div>
+    <Button
+      type="primary"
+      onClick={() =>
+        Notification.info({ ...opts, content: '我三秒后会被关闭', position: randomPos() })
+      }
+    >
+      After 3s
+    </Button>
+    <Button
+      type="primary"
+      onClick={() => Notification.open({ ...opts, duration: 2, position: 'topRight' })}
+    >
+      After 2s
+    </Button>
+  </div>
+);
+
+_Notification.story = {
+  name: 'notification',
+};
+
+export const ManaulOpenClose = () => (
+  <div>
+    <Button type="primary" onClick={fnc}>
+      Duration:0
+    </Button>
+    <Button type="primary" onClick={remove}>
+      remove duration:
+    </Button>
+  </div>
+);
+
+ManaulOpenClose.story = {
+  name: 'manaul open & close',
+};
 
-    componentDidMount() {
-        this.onClick();
-    }
+export const Position = () => {
+  let opts = {
+    duration: 0,
+    position: 'topRight',
+    content: 'semi-ui-notification',
+    title: 'Hi bytedance',
+  };
+  return (
+    <>
+      <Button onClick={() => Notification.info({ ...opts, position: 'top' })}>top</Button>
+      <Button onClick={() => Notification.info({ ...opts, position: 'topLeft' })}>topLeft</Button>
+      <Button onClick={() => Notification.info(opts)}>topRight</Button>
+      <Button onClick={() => Notification.info({ ...opts, position: 'bottom' })}>bottom</Button>
+      <Button onClick={() => Notification.info({ ...opts, position: 'bottomRight' })}>
+        bottomRight
+      </Button>
+      <Button onClick={() => Notification.info({ ...opts, position: 'bottomLeft' })}>
+        bottomLeft
+      </Button>
+    </>
+  );
+};
+
+export const CustomIcon = () => {
+  let opts = {
+    duration: 0,
+    position: 'topRight',
+    content: 'semi-ui-notification',
+    title: 'Hi bytedance',
+  };
+  return (
+    <>
+      <Button onClick={() => Notification.info({ ...opts, position: 'top' })}>info</Button>
+      <Button onClick={() => Notification.warning({ ...opts, position: 'top' })}>warning</Button>
+      <Button
+        onClick={() =>
+          Notification.info({
+            ...opts,
+            position: 'top',
+            icon: <IconWifi style={{ color: 'green' }} />,
+          })
+        }
+      >
+        wifi
+      </Button>
+      <Button
+        onClick={() =>
+          Notification.info({
+            ...opts,
+            position: 'bottomLeft',
+            icon: <IconToutiaoLogo style={{ color: 'red' }} />,
+          })
+        }
+      >
+        toutiao
+      </Button>
+    </>
+  );
+};
+
+export const EventDemo = () => {
+  let opts = {
+    duration: 0,
+    position: 'topRight',
+    content: 'semi-ui-notification',
+    title: 'Hi bytedance',
+    onClick: e => console.log('clicking'),
+    onClose: e => console.log('closing da da da...'),
+    onCloseClick: e => console.log('you closed me'),
+  };
+  return (
+    <>
+      <Button onClick={() => Notification.info({ ...opts, position: 'top' })}>info</Button>
+      <Button onClick={() => Notification.warning({ ...opts, position: 'top' })}>warning</Button>
+      <Button
+        onClick={() =>
+          Notification.info({
+            ...opts,
+            position: 'top',
+            icon: <IconWifi style={{ color: 'green' }} />,
+          })
+        }
+      >
+        wifi
+      </Button>
+      <Button
+        onClick={() =>
+          Notification.info({
+            ...opts,
+            position: 'bottomLeft',
+            icon: <IconToutiaoLogo style={{ color: 'red' }} />,
+          })
+        }
+      >
+        toutiao
+      </Button>
+    </>
+  );
+};
 
-    onClick() {
+class Demo extends React.Component {
+  constructor() {
+    super();
+    this.state = { test: 0 };
+    this.onClick = this.onClick.bind(this);
+  }
+
+  componentDidMount() {
+    this.onClick();
+  }
+
+  onClick() {
+    this.setState(
+      {
+        test: 1,
+      },
+      () => {
         this.setState(
-            {
-                test: 1,
-            },
-            () => {
-                this.setState(
-                    {
-                        test: 2,
-                    },
-                    () => {
-                        this.id = Notification.success({
-                            title: 'success',
-                            duration: 3,
-                        });
-                    }
-                );
-            }
+          {
+            test: 2,
+          },
+          () => {
+            this.id = Notification.success({
+              title: 'success',
+              duration: 3,
+            });
+          }
         );
-    }
+      }
+    );
+  }
 
-    render() {
-        return <Button>test</Button>;
-    }
+  render() {
+    return <Button>test</Button>;
+  }
 }
 
-stories.add('useNotification demo', () => <UseNotificationDemo />);
+export const _UseNotificationDemo = () => <UseNotificationDemo />;
 
-stories.add('二次异步回调', () => <Demo />);
+_UseNotificationDemo.story = {
+  name: 'useNotification demo',
+};
+
+export const AsyncCallback = () => <Demo />;
+AsyncCallback.story = {
+  name: '二次异步回调'
+}

+ 313 - 254
packages/semi-ui/overflowList/_story/overflowList.stories.js

@@ -1,297 +1,356 @@
 import React, { useState } from 'react';
-import { storiesOf } from '@storybook/react';
 import { Icon, Tag, Table, Slider } from '../../index';
 import OverflowList from '..';
-import { IconAlarm, IconCamera, IconBookmark, IconDuration, IconEdit, IconFolder, IconFolderOpen, IconBolt } from '@douyinfe/semi-icons';
+import {
+  IconAlarm,
+  IconCamera,
+  IconBookmark,
+  IconDuration,
+  IconEdit,
+  IconFolder,
+  IconFolderOpen,
+  IconBolt,
+} from '@douyinfe/semi-icons';
 
-const stories = storiesOf('OverflowList', module);
-
-// stories.addDecorator(withKnobs);;
+export default {
+  title: 'OverflowList'
+}
 
 const ITEMS = [
-    { icon: <IconFolderOpen />, key: "All" },
-    { icon: <IconFolderOpen />, key: "Users" },
-    { icon: <IconFolderOpen />, key: "Janet" },
-    { href: "#", icon: <IconFolderOpen />, key: "Photos" },
-    { href: "#", icon: <IconFolderOpen />, key: "Wednesday" },
-    { icon: <IconBolt />, key: "image", current: true },
+  { icon: <IconFolderOpen />, key: 'All' },
+  { icon: <IconFolderOpen />, key: 'Users' },
+  { icon: <IconFolderOpen />, key: 'Janet' },
+  { href: '#', icon: <IconFolderOpen />, key: 'Photos' },
+  { href: '#', icon: <IconFolderOpen />, key: 'Wednesday' },
+  { icon: <IconBolt />, key: 'image', current: true },
 ];
 
 class Demo extends React.Component {
-    renderOverflow = (items) => {
-        // console.log('overflow items: ', items);
-        return (<Tag>{items.length}</Tag>)
-    }
-    renderItem = (item, ind) => {
-        // console.log('visible item: ', item);
-        return (<span key={item.key} style={{ marginRight: 8 }}>{item.key}</span>)
-    }
-    render() {
-        return (
-            <div style={{ width: '30%' }}>
-                <OverflowList
-                    items={ITEMS}
-                    overflowRenderer={this.renderOverflow}
-                    visibleItemRenderer={this.renderItem}
-                />
-            </div>
-        );
-    }
+  renderOverflow = items => {
+    // console.log('overflow items: ', items);
+    return <Tag>{items.length}</Tag>;
+  };
+  renderItem = (item, ind) => {
+    // console.log('visible item: ', item);
+    return (
+      <span key={item.key} style={{ marginRight: 8 }}>
+        {item.key}
+      </span>
+    );
+  };
+  render() {
+    return (
+      <div style={{ width: '30%' }}>
+        <OverflowList
+          items={ITEMS}
+          overflowRenderer={this.renderOverflow}
+          visibleItemRenderer={this.renderItem}
+        />
+      </div>
+    );
+  }
 }
 
-stories.add('a simple overflow list', () => <Demo />);
+export const ASimpleOverflowList = () => <Demo />;
+
+ASimpleOverflowList.story = {
+  name: 'a simple semi overflow list',
+};
 
 class StartCollapse extends React.Component {
-    renderOverflow = (items) => {
-        // console.log('overflow items: ', items);
-        return (<Tag>{items.length}</Tag>)
-    }
-    renderItem = (item, ind) => {
-        // console.log('visible item: ', item);
-        return (<span key={item.key} style={{ marginRight: 8 }}>{item.key}</span>)
-    }
-    render() {
-        return (
-            <div style={{ width: '30%' }}>
-                <OverflowList
-                    items={ITEMS}
-                    collapseFrom="start"
-                    overflowRenderer={this.renderOverflow}
-                    visibleItemRenderer={this.renderItem}
-                />
-            </div>
-        );
-    }
+  renderOverflow = items => {
+    // console.log('overflow items: ', items);
+    return <Tag>{items.length}</Tag>;
+  };
+  renderItem = (item, ind) => {
+    // console.log('visible item: ', item);
+    return (
+      <span key={item.key} style={{ marginRight: 8 }}>
+        {item.key}
+      </span>
+    );
+  };
+  render() {
+    return (
+      <div style={{ width: '30%' }}>
+        <OverflowList
+          items={ITEMS}
+          collapseFrom="start"
+          overflowRenderer={this.renderOverflow}
+          visibleItemRenderer={this.renderItem}
+        />
+      </div>
+    );
+  }
 }
 
-stories.add('collapse from start', () => <StartCollapse />);
+export const CollapseFromStart = () => <StartCollapse />;
+
+CollapseFromStart.story = {
+  name: 'collapse from start',
+};
 
 class MinCollapse extends React.Component {
-    renderOverflow = (items) => {
-        // console.log('overflow items: ', items);
-        return (<Tag>{items.length}</Tag>)
-    }
-    renderItem = (item, ind) => {
-        // console.log('visible item: ', item);
-        return (<span key={item.key} style={{ marginRight: 8 }}>{item.key}</span>)
-    }
-    render() {
-        return (
-            <div style={{ width: '30%' }}>
-                <OverflowList
-                    items={ITEMS}
-                    minVisibleItems={3}
-                    overflowRenderer={this.renderOverflow}
-                    visibleItemRenderer={this.renderItem}
-                    onOverflow={(item) => console.log(item)}
-                />
-            </div>
-        );
-    }
+  renderOverflow = items => {
+    // console.log('overflow items: ', items);
+    return <Tag>{items.length}</Tag>;
+  };
+  renderItem = (item, ind) => {
+    // console.log('visible item: ', item);
+    return (
+      <span key={item.key} style={{ marginRight: 8 }}>
+        {item.key}
+      </span>
+    );
+  };
+  render() {
+    return (
+      <div style={{ width: '30%' }}>
+        <OverflowList
+          items={ITEMS}
+          minVisibleItems={3}
+          overflowRenderer={this.renderOverflow}
+          visibleItemRenderer={this.renderItem}
+          onOverflow={item => console.log(item)}
+        />
+      </div>
+    );
+  }
 }
 
-stories.add('minVisibleItems', () => <MinCollapse />);
+export const MinVisibleItems = () => <MinCollapse />;
+
+MinVisibleItems.story = {
+  name: 'minVisibleItems',
+};
 
 class OverlapDemo extends React.Component {
-    renderOverflow = (items) => {
-        return items.map(item => <Tag>{item.length}</Tag>)
-    }
-    renderItem = (item, ind) => {
-        return (<div key={item.key} style={{ marginRight: 8 }}>{item.key}</div>)
-    }
-    render() {
-        return (
-            <div style={{ width: '40%' }}>
-                <OverflowList
-                    items={ITEMS}
-                    overflowRenderer={this.renderOverflow}
-                    visibleItemRenderer={this.renderItem}
-                    renderMode="scroll"
-                />
-            </div>
-        );
-    }
+  renderOverflow = items => {
+    return items.map(item => <Tag>{item.length}</Tag>);
+  };
+  renderItem = (item, ind) => {
+    return (
+      <div key={item.key} style={{ marginRight: 8 }}>
+        {item.key}
+      </div>
+    );
+  };
+  render() {
+    return (
+      <div style={{ width: '40%' }}>
+        <OverflowList
+          items={ITEMS}
+          overflowRenderer={this.renderOverflow}
+          visibleItemRenderer={this.renderItem}
+          renderMode="scroll"
+        />
+      </div>
+    );
+  }
 }
 
-stories.add('overlap overflow list', () => <OverlapDemo />);
+export const OverlapOverflowList = () => <OverlapDemo />;
 
+OverlapOverflowList.story = {
+  name: 'overlap overflow list',
+};
 
 class OverlapDemo2 extends React.Component {
-    renderOverflow = (items) => {
-        return items.map(item => <Tag>{item.length}</Tag>)
-    }
-    renderItem = (item, ind) => {
-        return (<div key={item.key} style={{ marginRight: 8 }}>{item.key}</div>)
-    }
-    render() {
-        return (
-            <div style={{ width: '40%' }}>
-                <OverflowList
-                    items={ITEMS}
-                    threshold={0.2}
-                    onIntersect={(item) => console.log(item)}
-                    overflowRenderer={this.renderOverflow}
-                    visibleItemRenderer={this.renderItem}
-                    renderMode="scroll"
-                />
-            </div>
-        );
-    }
+  renderOverflow = items => {
+    return items.map(item => <Tag>{item.length}</Tag>);
+  };
+  renderItem = (item, ind) => {
+    return (
+      <div key={item.key} style={{ marginRight: 8 }}>
+        {item.key}
+      </div>
+    );
+  };
+  render() {
+    return (
+      <div style={{ width: '40%' }}>
+        <OverflowList
+          items={ITEMS}
+          threshold={0.2}
+          onIntersect={item => console.log(item)}
+          overflowRenderer={this.renderOverflow}
+          visibleItemRenderer={this.renderItem}
+          renderMode="scroll"
+        />
+      </div>
+    );
+  }
 }
 
-stories.add('overlap overflow threshold', () => <OverlapDemo2 />);
+export const OverlapOverflowThreshold = () => <OverlapDemo2 />;
+
+OverlapOverflowThreshold.story = {
+  name: 'overlap overflow threshold',
+};
 
 const data = [
-    {
-        key: '1',
-        name: 'John Brown',
-        age: 32,
-        age1: 23,
-        age2: 11,
-        address: [1, 2, 3, 4, 5],
-    },
-    {
-        key: '2',
-        name: 'Jim Green',
-        age: 42,
-        age1: 23,
-        age2: 11,
-        address: [1, 2, 3, 4, 5],
-    },
-    {
-        key: '3',
-        name: 'Joe Black',
-        age: 32,
-        age1: 23,
-        age2: 11,
-        address: [1, 2, 3, 4, 5],
-    },
-    {
-        key: '4',
-        name: 'Disabled User',
-        age: 99,
-        age1: 23,
-        age2: 11,
-        address: [1, 2, 3, 4, 5],
-    },
+  {
+    key: '1',
+    name: 'John Brown',
+    age: 32,
+    age1: 23,
+    age2: 11,
+    address: [1, 2, 3, 4, 5],
+  },
+  {
+    key: '2',
+    name: 'Jim Green',
+    age: 42,
+    age1: 23,
+    age2: 11,
+    address: [1, 2, 3, 4, 5],
+  },
+  {
+    key: '3',
+    name: 'Joe Black',
+    age: 32,
+    age1: 23,
+    age2: 11,
+    address: [1, 2, 3, 4, 5],
+  },
+  {
+    key: '4',
+    name: 'Disabled User',
+    age: 99,
+    age1: 23,
+    age2: 11,
+    address: [1, 2, 3, 4, 5],
+  },
 ];
 
 class TableDemo extends React.Component {
-    renderOverflow = (items) => {
-        return <Tag>{items.length}</Tag>
-    }
-    renderItem = (item, ind) => {
-        return (<div key={`${ind}-item`} style={{ marginRight: 8 }}>{item}</div>)
-    }
-    renderColumn(items) {
-        return (
-            <div
-            // style={{ width: '99%' }}
-            >
-                <OverflowList
-                    items={items.concat(items)}
-                    // observeAll={true}
-                    style={{ width: 88 }}
-                    overflowRenderer={items => <Tag>{items.length}</Tag>}
-                    visibleItemRenderer={(item, ind) => <div key={`${ind}-item`} style={{ marginRight: 8 }}>{item}</div>}
-                />
+  renderOverflow = items => {
+    return <Tag>{items.length}</Tag>;
+  };
+  renderItem = (item, ind) => {
+    return (
+      <div key={`${ind}-item`} style={{ marginRight: 8 }}>
+        {item}
+      </div>
+    );
+  };
+  renderColumn(items) {
+    return (
+      <div
+      // style={{ width: '99%' }}
+      >
+        <OverflowList
+          items={items.concat(items)}
+          // observeAll={true}
+          style={{ width: 88 }}
+          overflowRenderer={items => <Tag>{items.length}</Tag>}
+          visibleItemRenderer={(item, ind) => (
+            <div key={`${ind}-item`} style={{ marginRight: 8 }}>
+              {item}
             </div>
-        );
-        // return (
-        //     <div>
-        //         <OverflowList
-        //             items={items.concat(items)}
-        //             style={{ width: 88 }}
-        //             overflowRenderer={this.renderOverflow}
-        //             visibleItemRenderer={this.renderItem}
-        //         />
-        //     </div>
-        // );
-    }
-    render() {
-        const columns = [
-            {
-                title: 'Name',
-                dataIndex: 'name',
-                width: '30%',
-            },
-            {
-                title: 'combine',
-                dataIndex: 'test',
-                children: [
-                    {
-                        title: 'Age',
-                        children: [
-                            {
-                                title: 'Age1',
-                                dataIndex: 'age1',
-                            },
-                            {
-                                title: 'Age2',
-                                dataIndex: 'age2',
-                            },
-                        ],
-                    },
-                    {
-                        title: 'Key',
-                        dataIndex: 'key',
-                    },
-                ],
-            },
-            {
-                title: 'Address',
-                width: '20%',
-                dataIndex: 'address',
-                render: item => this.renderColumn(item),
-                className: 'table-width-test'
-            },
-        ];
-        return <Table columns={columns} dataSource={data} />
-    }
+          )}
+        />
+      </div>
+    );
+    // return (
+    //     <div>
+    //         <OverflowList
+    //             items={items.concat(items)}
+    //             style={{ width: 88 }}
+    //             overflowRenderer={this.renderOverflow}
+    //             visibleItemRenderer={this.renderItem}
+    //         />
+    //     </div>
+    // );
+  }
+  render() {
+    const columns = [
+      {
+        title: 'Name',
+        dataIndex: 'name',
+        width: '30%',
+      },
+      {
+        title: 'combine',
+        dataIndex: 'test',
+        children: [
+          {
+            title: 'Age',
+            children: [
+              {
+                title: 'Age1',
+                dataIndex: 'age1',
+              },
+              {
+                title: 'Age2',
+                dataIndex: 'age2',
+              },
+            ],
+          },
+          {
+            title: 'Key',
+            dataIndex: 'key',
+          },
+        ],
+      },
+      {
+        title: 'Address',
+        width: '20%',
+        dataIndex: 'address',
+        render: item => this.renderColumn(item),
+        className: 'table-width-test',
+      },
+    ];
+    return <Table columns={columns} dataSource={data} />;
+  }
 }
 
-stories.add('overflow in table', () => <TableDemo />);
+export const OverflowInTable = () => <TableDemo />;
+
+OverflowInTable.story = {
+  name: 'overflow in table',
+};
 
 const LargeData = () => {
-    const [width, setWidth] = useState(100)
-    const renderOverflow = (items) => {
-        // console.log('overflow items: ', items);
-        return (items.length ? <Tag style={{ flex: '0 0 auto' }}>+{items.length}</Tag> : null)
-    }
-    const renderItem = (item, ind) => {
-        // console.log('visible item: ', item);
-        return (
-            <Tag color='blue' key={item.key} style={{ marginRight: 8, flex: '0 0 auto' }}>
-                {item.icon}
-                {item.key}
-            </Tag>
-        )
-    }
-    const items = [
-            { icon: <IconAlarm style={{ marginRight: 4 }} />, key: "alarm" },
-            { icon: <IconBookmark style={{ marginRight: 4 }} />, key: "bookmark" },
-            { icon: <IconCamera style={{ marginRight: 4 }} />, key: "camera" },
-            { icon: <IconDuration style={{ marginRight: 4 }} />, key: "duration" },
-            { icon: <IconEdit style={{ marginRight: 4 }} />, key: "edit" },
-            { icon: <IconFolder style={{ marginRight: 4 }} />, key: "folder" },
-        ];
-        
+  const [width, setWidth] = useState(100);
+  const renderOverflow = items => {
+    // console.log('overflow items: ', items);
+    return items.length ? <Tag style={{ flex: '0 0 auto' }}>+{items.length}</Tag> : null;
+  };
+  const renderItem = (item, ind) => {
+    // console.log('visible item: ', item);
     return (
-        <div>
-            <Slider step={1} value={width} onChange={(value) => setWidth(value)} />
-            <br/>
-            <br/>
-            <div style={{ width: `${width}%` }}>
-                <OverflowList
-                    items={items}
-                    minVisibleItems={3}
-                    overflowRenderer={renderOverflow}
-                    visibleItemRenderer={renderItem}
-                />
-            </div>
-        </div>
+      <Tag color="blue" key={item.key} style={{ marginRight: 8, flex: '0 0 auto' }}>
+        {item.icon}
+        {item.key}
+      </Tag>
     );
-}
+  };
+  const items = [
+    { icon: <IconAlarm style={{ marginRight: 4 }} />, key: 'alarm' },
+    { icon: <IconBookmark style={{ marginRight: 4 }} />, key: 'bookmark' },
+    { icon: <IconCamera style={{ marginRight: 4 }} />, key: 'camera' },
+    { icon: <IconDuration style={{ marginRight: 4 }} />, key: 'duration' },
+    { icon: <IconEdit style={{ marginRight: 4 }} />, key: 'edit' },
+    { icon: <IconFolder style={{ marginRight: 4 }} />, key: 'folder' },
+  ];
+
+  return (
+    <div>
+      <Slider step={1} value={width} onChange={value => setWidth(value)} />
+      <br />
+      <br />
+      <div style={{ width: `${width}%` }}>
+        <OverflowList
+          items={items}
+          minVisibleItems={3}
+          overflowRenderer={renderOverflow}
+          visibleItemRenderer={renderItem}
+        />
+      </div>
+    </div>
+  );
+};
 
 // TODO large data will cause memory heap
 // stories.add('large amount of data', () => <LargeData />);

+ 124 - 107
packages/semi-ui/pagination/_story/pagination.stories.js

@@ -1,131 +1,148 @@
 import React, { useState } from 'react';
-import { storiesOf } from '@storybook/react';
-// import { withKnobs, text, boolean } from '@storybook/addon-knobs';
-import withPropsCombinations from 'react-storybook-addon-props-combinations';
 
 import 'normalize.css';
 import { Button } from '../../index';
 import Pagination from '../index';
 
-const stories = storiesOf('Pagination', module);
+export default {
+  title: 'Pagination'
+}
 
-// stories.addDecorator(withKnobs);;
+export const PaginationSmall = () => <Pagination total={90} size="small"></Pagination>;
 
-stories.add('Pagination small', () => (
-    <Pagination total={90} size="small"></Pagination>
-));
+PaginationSmall.story = {
+  name: 'Pagination small',
+};
 
-stories.add('Pagination default', () => (
-    <div>
-        <Pagination total={1}></Pagination>
-        <Pagination total={0}></Pagination>
-        <Pagination total={9}></Pagination>
-        <Pagination total={30}></Pagination>
-        <Pagination total={80}></Pagination>
-        <Pagination total={200}></Pagination>
-        <Pagination total={80} pageSize={30}></Pagination>
-        <Pagination total={1000000000} ></Pagination>
-    </div>
-));
+export const PaginationDefault = () => (
+  <div>
+    <Pagination total={1}></Pagination>
+    <Pagination total={0}></Pagination>
+    <Pagination total={9}></Pagination>
+    <Pagination total={30}></Pagination>
+    <Pagination total={80}></Pagination>
+    <Pagination total={200}></Pagination>
+    <Pagination total={80} pageSize={30}></Pagination>
+    <Pagination total={1000000000}></Pagination>
+  </div>
+);
+
+PaginationDefault.story = {
+  name: 'Pagination default',
+};
 
-stories.add('Pagination hideOnSinglePage', () => (
-    <div>
-        <Pagination total={1} hideOnSinglePage></Pagination>
-        <Pagination total={0} hideOnSinglePage></Pagination>
-        <Pagination total={9} hideOnSinglePage></Pagination>
-        <Pagination total={30} hideOnSinglePage></Pagination>
-    </div>
-));
+export const PaginationHideOnSinglePage = () => (
+  <div>
+    <Pagination total={1} hideOnSinglePage></Pagination>
+    <Pagination total={0} hideOnSinglePage></Pagination>
+    <Pagination total={9} hideOnSinglePage></Pagination>
+    <Pagination total={30} hideOnSinglePage></Pagination>
+  </div>
+);
+
+PaginationHideOnSinglePage.story = {
+  name: 'Pagination hideOnSinglePage',
+};
 
-stories.add('Pagination 指定当前页', () => (
-    <div>
-        <Pagination total={20000} defaultCurrentPage={2}></Pagination>
-    </div>
-));
+export const DefaultCurrentPageDemo = () => (
+  <div>
+    <Pagination total={20000} defaultCurrentPage={2}></Pagination>
+  </div>
+);
 
-const ControlPage = () => {
-    const [page, setPage] = useState(3);
-    function onPageChange(currentPage) {
-        setPage(currentPage);
-    }
-    return (
-        <div>
-            <Pagination total={200} currentPage={page} onPageChange={onPageChange}></Pagination>
-        </div>
-    );
+DefaultCurrentPageDemo.story = {
+  name: 'Pagination 指定当前页',
 };
-stories.add('Pagination 页码受控', () => <ControlPage />);
 
-stories.add('Pagination showPageSizeChanger', () => (
+const ControlPage = () => {
+  const [page, setPage] = useState(3);
+  function onPageChange(currentPage) {
+    setPage(currentPage);
+  }
+  return (
     <div>
-        <Pagination total={100} showSizeChanger showTotal></Pagination>
-        <Pagination total={200}></Pagination>
-        <Pagination total={300}
-            showSizeChanger
-            pageSizeOpts={[10, 20, 50, 200]}
-            onPageChange={(page, pageSize)=>console.log(`pageChange:${page},pageSize:${pageSize}`)}
-            onPageSizeChange={pageSize=>console.log(`pageSizeChange${pageSize}`)}
-        >
-        </Pagination>
-        <Pagination total={300} showSizeChanger></Pagination>
+      <Pagination total={200} currentPage={page} onPageChange={onPageChange}></Pagination>
     </div>
-));
+  );
+};
+export const ControlledPageDemo = () => <ControlPage />;
 
-stories.add('Pagination pageSizeOpts', () => (
-    <div>
-        <Pagination total={80} showSizeChanger></Pagination>
-        <Pagination total={200}></Pagination>
-        
-        <Pagination total={300} showSizeChanger pageSizeOpts={[50, 80, 90, 200]}></Pagination>
-    </div>
-));
+ControlledPageDemo.story = {
+  name: 'Pagination 页码受控',
+};
 
-stories.add('Pagination showQuickJumper', () => (
-    <div>
-        <Pagination total={1} showSizeChanger showQuickJumper></Pagination>
-        <Pagination total={80} showSizeChanger showQuickJumper></Pagination>
-        <Pagination total={200} showQuickJumper></Pagination>
-        <Pagination total={300} showSizeChanger pageSizeOpts={[50, 80, 90, 200]} showQuickJumper></Pagination>
-    </div>
-));
+export const PaginationShowPageSizeChanger = () => (
+  <div>
+    <Pagination total={100} showSizeChanger showTotal></Pagination>
+    <Pagination total={200}></Pagination>
+    <Pagination
+      total={300}
+      showSizeChanger
+      pageSizeOpts={[10, 20, 50, 200]}
+      onPageChange={(page, pageSize) => console.log(`pageChange:${page},pageSize:${pageSize}`)}
+      onPageSizeChange={pageSize => console.log(`pageSizeChange${pageSize}`)}
+    ></Pagination>
+    <Pagination total={300} showSizeChanger></Pagination>
+  </div>
+);
+
+PaginationShowPageSizeChanger.story = {
+  name: 'Pagination showPageSizeChanger',
+};
 
+export const PaginationPageSizeOpts = () => (
+  <div>
+    <Pagination total={80} showSizeChanger></Pagination>
+    <Pagination total={200}></Pagination>
 
+    <Pagination total={300} showSizeChanger pageSizeOpts={[50, 80, 90, 200]}></Pagination>
+  </div>
+);
+
+PaginationPageSizeOpts.story = {
+  name: 'Pagination pageSizeOpts',
+};
+
+export const PaginationShowQuickJumper = () => (
+  <div>
+    <Pagination total={1} showSizeChanger showQuickJumper></Pagination>
+    <Pagination total={80} showSizeChanger showQuickJumper></Pagination>
+    <Pagination total={200} showQuickJumper></Pagination>
+    <Pagination
+      total={300}
+      showSizeChanger
+      pageSizeOpts={[50, 80, 90, 200]}
+      showQuickJumper
+    ></Pagination>
+  </div>
+);
+
+PaginationShowQuickJumper.story = {
+  name: 'Pagination showQuickJumper',
+};
 
 const DynamicPageSize = () => {
-    const [pageSize, setPageSize] = useState(10); 
-    function changePageSize() {
-        let map = {
-            10: 40,
-            40: 100,
-            100: 20,
-            100: 10
-        }
-        setPageSize(map[pageSize]);
-    }
-    return (
-        <>
-        <Pagination
-            total={200}
-            showSizeChanger
-            pageSize={pageSize}
-         >
-        </Pagination>
-        <br/>
-        <Button onClick={changePageSize}>change</Button>
-        </>
-    );
+  const [pageSize, setPageSize] = useState(10);
+  function changePageSize() {
+    let map = {
+      10: 40,
+      40: 100,
+      100: 20,
+      100: 10,
+    };
+    setPageSize(map[pageSize]);
+  }
+  return (
+    <>
+      <Pagination total={200} showSizeChanger pageSize={pageSize}></Pagination>
+      <br />
+      <Button onClick={changePageSize}>change</Button>
+    </>
+  );
 };
 
-stories.add('Pagination dynamic update pageSize', () => <DynamicPageSize />);
-
-// stories.add('combination', withPropsCombinations(
-//     Button,
-//     {
-//         disaled: [false, true],
-//         children: ['hello button'],
-//         size: ['large', 'default', 'small'],
-//         type: ['default', 'primary', 'warning', 'danger'],
-//         // block: [false, true],
-//         ghost: [false, true]
-//     }
-// ));
+export const PaginationDynamicUpdatePageSize = () => <DynamicPageSize />;
+
+PaginationDynamicUpdatePageSize.story = {
+  name: 'Pagination dynamic update pageSize',
+};

+ 112 - 79
packages/semi-ui/popconfirm/_story/popconfirm.stories.js

@@ -1,7 +1,4 @@
 import React, { useState } from 'react';
-import { storiesOf } from '@storybook/react';
-// import { withKnobs, text, boolean } from '@storybook/addon-knobs';
-import withPropsCombinations from 'react-storybook-addon-props-combinations';
 
 import Popconfirm from '../index';
 import Button from '../../button';
@@ -14,95 +11,131 @@ import TitleConfirmDemo from './TitlePopconfirm';
 import InTableDemo from './InTable';
 import ShowArrow from './ShowArrow';
 
-const stories = storiesOf('popconfirm', module);
-
-// stories.addDecorator(withKnobs);;
+export default {
+  title: 'Popconfirm',
+  parameters: {
+    chromatic: { disableSnapshot: true },
+  },
+}
 
 let style = {
-    display: 'inline-block',
-    padding: '20px',
+  display: 'inline-block',
+  padding: '20px',
 };
 
-stories.add('simple', () => (
-    <div>
-        <div style={style}>
-            <Popconfirm
-                title="确定是否要保存此修改?确定是否要保存此修改?确定是否要保存此修改?确定是否要保存此修改?确定是否要保存此修改?确定是否要保存此修改?确定是否要保存此修改?确定是否要保存此修改?"
-                content="此修改将不可逆"
-            >
-                <a>Delete</a>
-            </Popconfirm>
-        </div>
+export const Simple = () => (
+  <div>
+    <div style={style}>
+      <Popconfirm
+        title="确定是否要保存此修改?确定是否要保存此修改?确定是否要保存此修改?确定是否要保存此修改?确定是否要保存此修改?确定是否要保存此修改?确定是否要保存此修改?确定是否要保存此修改?"
+        content="此修改将不可逆"
+      >
+        <a>Delete</a>
+      </Popconfirm>
     </div>
-));
-
-stories.add('button', () => (
-    <div>
-        <div style={style}>
-            <Popconfirm position="bottomLeft" title="确定是否要保存此修改?" content="此修改将不可逆">
-                <Button>Save</Button>
-            </Popconfirm>
-        </div>
+  </div>
+);
+
+Simple.story = {
+  name: 'simple',
+};
+
+export const _Button = () => (
+  <div>
+    <div style={style}>
+      <Popconfirm position="bottomLeft" title="确定是否要保存此修改?" content="此修改将不可逆">
+        <Button>Save</Button>
+      </Popconfirm>
     </div>
-));
+  </div>
+);
+
+_Button.story = {
+  name: 'button',
+};
 
 const dataSource = [
-    {
-        key: '1',
-        name: 'John Brown',
-        age: 32,
-        address: 'New York No. 1 Lake Park, New York No. 1 Lake Park',
-    },
-    {
-        key: '2',
-        name: 'Jim Green',
-        age: 42,
-        address: 'London No. 1 Lake Park',
-    },
-    {
-        key: '3',
-        name: 'Joe Black',
-        age: 32,
-        address: 'Sidney No. 1 Lake Park',
-    },
-    {
-        key: '4',
-        name: 'Disabled User',
-        age: 99,
-        address: 'Sidney No. 1 Lake Park',
-    },
+  {
+    key: '1',
+    name: 'John Brown',
+    age: 32,
+    address: 'New York No. 1 Lake Park, New York No. 1 Lake Park',
+  },
+  {
+    key: '2',
+    name: 'Jim Green',
+    age: 42,
+    address: 'London No. 1 Lake Park',
+  },
+  {
+    key: '3',
+    name: 'Joe Black',
+    age: 32,
+    address: 'Sidney No. 1 Lake Park',
+  },
+  {
+    key: '4',
+    name: 'Disabled User',
+    age: 99,
+    address: 'Sidney No. 1 Lake Park',
+  },
 ];
 const columns = [
-    {
-        title: 'Name',
-        dataIndex: 'name',
-        render: text => (
-            <Popconfirm position="bottomLeft" title="确定是否要保存此修改?" content="此修改将不可逆">
-                <Button>{text}</Button>
-            </Popconfirm>
-        ),
-    },
-    {
-        title: 'Age',
-        dataIndex: 'age',
-    },
-    {
-        title: 'Address',
-        dataIndex: 'address',
-    },
+  {
+    title: 'Name',
+    dataIndex: 'name',
+    render: text => (
+      <Popconfirm position="bottomLeft" title="确定是否要保存此修改?" content="此修改将不可逆">
+        <Button>{text}</Button>
+      </Popconfirm>
+    ),
+  },
+  {
+    title: 'Age',
+    dataIndex: 'age',
+  },
+  {
+    title: 'Address',
+    dataIndex: 'address',
+  },
 ];
 
-stories.add('table', () => (
-    <div>
-        <Table dataSource={dataSource} columns={columns} />
-    </div>
-));
+export const _Table = () => (
+  <div>
+    <Table dataSource={dataSource} columns={columns} />
+  </div>
+);
 
-stories.add('types-confirm', () => <TypesConfrimDemo />);
+_Table.story = {
+  name: 'table',
+};
 
-stories.add('dynamic disable', () => <DynamicDisableDemo />);
+export const TypesConfirm = () => <TypesConfrimDemo />;
+
+TypesConfirm.story = {
+  name: 'types-confirm',
+};
+
+export const DynamicDisable = () => <DynamicDisableDemo />;
+
+DynamicDisable.story = {
+  name: 'dynamic disable',
+};
+
+export const TitlePopconfirm = () => <TitleConfirmDemo />;
+
+TitlePopconfirm.story = {
+  name: 'title popconfirm',
+};
+
+export const InTable = () => <InTableDemo />;
+
+InTable.story = {
+  name: 'in table',
+};
 
-stories.add('title popconfirm', () => <TitleConfirmDemo />);
 
-stories.add('in table', () => <InTableDemo />);
-stories.add(`show arrow`, () => <ShowArrow />);
+export const ShowArrowDemo = () => <ShowArrow />;
+ShowArrowDemo.style = {
+  name: 'show arrow'
+}

+ 523 - 456
packages/semi-ui/popover/_story/popover.stories.js

@@ -1,7 +1,5 @@
 import React, { useState } from 'react';
-import { storiesOf } from '@storybook/react'; // import { withKnobs, text, boolean } from '@storybook/addon-knobs';
 
-import withPropsCombinations from 'react-storybook-addon-props-combinations';
 import Popover from '../index';
 import { strings } from '@douyinfe/semi-foundation/tooltip/constants';
 import { Button, Input, Table, IconButton, Modal, Tag } from '@douyinfe/semi-ui';
@@ -11,497 +9,566 @@ import PopRight from './PopRight';
 import NestedPopover from './NestedPopover';
 import ArrowPointAtCenter from './ArrowPointAtCenter';
 import { IconDelete } from '@douyinfe/semi-icons';
-const stories = storiesOf('popover', module); // stories.addDecorator(withKnobs);;
+
+export default {
+  title: 'Popover',
+  parameters: {
+    chromatic: { disableSnapshot: true },
+  },
+}
 
 let style = {
-    display: 'inline-block',
-    padding: '20px',
+  display: 'inline-block',
+  padding: '20px',
 };
-stories.add('popover', () => (
-    <div>
-        <div style={style}>
-            <Popover content="ies vigo" title="bytedance" position="bottom" visible={true} showArrow>
-                bottom hover
-            </Popover>
-        </div>
 
-        <div style={style}>
-            <Popover content="ies vigo" title="bytedance" trigger="click" position="bottom">
-                bottom click
-            </Popover>
-        </div>
+export const _Popover = () => (
+  <div>
+    <div style={style}>
+      <Popover content="ies vigo" title="bytedance" position="bottom" visible={true} showArrow>
+        bottom hover
+      </Popover>
+    </div>
 
-        <div style={style}>
-            <Popover content="ies vigo" title="bytedance" trigger="click" position="right">
-                <Button>Pos:right, trigger: Click</Button>
-            </Popover>
-        </div>
+    <div style={style}>
+      <Popover content="ies vigo" title="bytedance" trigger="click" position="bottom">
+        bottom click
+      </Popover>
+    </div>
 
-        <div style={style}>
-            <Popover content={<Button type="warning">btn</Button>} title="bytedance" trigger="click" position="right">
-                content is Node
-            </Popover>
-        </div>
+    <div style={style}>
+      <Popover content="ies vigo" title="bytedance" trigger="click" position="right">
+        <Button>Pos:right, trigger: Click</Button>
+      </Popover>
+    </div>
 
-        <div style={style}>
-            <Popover content={<Input />} title="bytedance" trigger="click" position="right">
-                content is Node
-            </Popover>
-        </div>
+    <div style={style}>
+      <Popover
+        content={<Button type="warning">btn</Button>}
+        title="bytedance"
+        trigger="click"
+        position="right"
+      >
+        content is Node
+      </Popover>
     </div>
-));
-stories.add('positions', () => (
-    <div
-        style={{
-            width: 480,
-            height: 360,
-            boxSizing: 'content-box',
-            padding: '150px 50px',
-            display: 'flex',
-            flexWrap: 'wrap',
-            justifyContent: 'space-evenly',
-        }}
-    >
-        {strings.POSITION_SET.map(pos => (
-            <Popover
-                key={pos}
-                content={
-                    <div
-                        style={{
-                            padding: 20,
-                        }}
-                    >
-                        <p>Hi Bytedancer!</p>
-                    </div>
-                }
-                trigger="click"
-                position={pos}
-            >
-                <Button key={pos}>{pos}</Button>
-            </Popover>
-        ))}
+
+    <div style={style}>
+      <Popover content={<Input />} title="bytedance" trigger="click" position="right">
+        content is Node
+      </Popover>
     </div>
-)); // TODO
-
-stories.add('popConfirm', () => (
-    <div>
-        <div style={style}>
-            <Popover isConfirmMode content="hi byteddance ies">
-                <a>IconDelete</a>
-            </Popover>
-        </div>
+  </div>
+);
+
+_Popover.story = {
+  name: 'popover',
+};
+
+export const Positions = () => (
+  <div
+    style={{
+      width: 480,
+      height: 360,
+      boxSizing: 'content-box',
+      padding: '150px 50px',
+      display: 'flex',
+      flexWrap: 'wrap',
+      justifyContent: 'space-evenly',
+    }}
+  >
+    {strings.POSITION_SET.map(pos => (
+      <Popover
+        key={pos}
+        content={
+          <div
+            style={{
+              padding: 20,
+            }}
+          >
+            <p>Hi Bytedancer!</p>
+          </div>
+        }
+        trigger="click"
+        position={pos}
+      >
+        <Button key={pos}>{pos}</Button>
+      </Popover>
+    ))}
+  </div>
+);
+
+Positions.story = {
+  name: 'positions',
+};
+
+export const PopConfirm = () => (
+  <div>
+    <div style={style}>
+      <Popover isConfirmMode content="hi byteddance ies">
+        <a>IconDelete</a>
+      </Popover>
     </div>
-));
+  </div>
+);
+
+PopConfirm.story = {
+  name: 'popConfirm',
+};
 
 class Demo extends React.Component {
-    constructor(props) {
-        super(props);
-        this.state = {
-            visible: false,
-        };
-        this.changeVisible = this.changeVisible.bind(this);
-        this.renderContent = this.renderContent.bind(this);
-    }
+  constructor(props) {
+    super(props);
+    this.state = {
+      visible: false,
+    };
+    this.changeVisible = this.changeVisible.bind(this);
+    this.renderContent = this.renderContent.bind(this);
+  }
 
-    changeVisible(visible = true) {
-        this.setState({
-            visible,
-        });
-    }
+  changeVisible(visible = true) {
+    this.setState({
+      visible,
+    });
+  }
 
-    renderContent() {
-        return (
-            <>
-                <p>hi byteddance ies</p>
-                <Button onClick={() => this.changeVisible(false)}>cancel</Button>
-                <Button onClick={() => this.changeVisible(false)}>confirm</Button>
-            </>
-        );
-    }
+  renderContent() {
+    return (
+      <>
+        <p>hi byteddance ies</p>
+        <Button onClick={() => this.changeVisible(false)}>cancel</Button>
+        <Button onClick={() => this.changeVisible(false)}>confirm</Button>
+      </>
+    );
+  }
 
-    render() {
-        const content = this.renderContent();
-        const { visible } = this.state;
-        return (
-            <Popover trigger="custom" content={content} visible={visible} position="bottomLeft">
-                <Button onClick={() => this.changeVisible(true)}>show Popover</Button>
-            </Popover>
-        );
-    }
+  render() {
+    const content = this.renderContent();
+    const { visible } = this.state;
+    return (
+      <Popover trigger="custom" content={content} visible={visible} position="bottomLeft">
+        <Button onClick={() => this.changeVisible(true)}>show Popover</Button>
+      </Popover>
+    );
+  }
 }
 
-stories.add('popover custom visible', () => <Demo />);
-stories.add('复合组件', () => {
-    class TableApp extends React.Component {
-        constructor(props) {
-            super(props);
-            this.raw = [
-                {
-                    key: '1',
-                    name: 'John Brown',
-                    age: 32,
-                    address: 'New York No. 1 Lake Park, New York No. 1 Lake Park',
-                },
-                {
-                    key: '2',
-                    name: 'Jim Green',
-                    age: 42,
-                    address: 'London No. 1 Lake Park',
-                },
-                {
-                    key: '3',
-                    name: 'Joe Black',
-                    age: 32,
-                    address: 'Sidney No. 1 Lake Park',
-                },
-                {
-                    key: '4',
-                    name: 'Disabled User',
-                    age: 99,
-                    address: 'Sidney No. 1 Lake Park',
-                },
-            ];
-            this.state = {
-                dataSource: [...this.raw],
-                modalVisible: false,
-                columns: [
-                    {
-                        title: 'Name',
-                        dataIndex: 'name',
-                        render: text => <a href="javascript:;">{text}</a>,
-                    },
-                    {
-                        title: 'Age',
-                        dataIndex: 'age',
-                    },
-                    {
-                        title: 'Address',
-                        dataIndex: 'address',
-                    },
-                    {
-                        title: 'Operation',
-                        render: (text, record) => (
-                            <div>
-                                <Button icon={<IconDelete />} onClick={() => this.removeRecord(record.key)} />
-                                <Button onClick={() => this.toggleModal(true)}>编辑</Button>
-                            </div>
-                        ),
-                    },
-                ],
-            };
-        }
+export const PopoverCustomVisible = () => <Demo />;
+
+PopoverCustomVisible.story = {
+  name: 'popover custom visible',
+};
 
-        removeRecord(key) {
-            let dataSource = [...this.state.dataSource];
 
-            if (key != null) {
-                let idx = dataSource.findIndex(data => data.key === key); // console.log(key, dataSource, idx);
+CompositeComponent.story = { name: '复合组件' };
+export function CompositeComponent() {
+  class TableApp extends React.Component {
+    constructor(props) {
+      super(props);
+      this.raw = [
+        {
+          key: '1',
+          name: 'John Brown',
+          age: 32,
+          address: 'New York No. 1 Lake Park, New York No. 1 Lake Park',
+        },
+        {
+          key: '2',
+          name: 'Jim Green',
+          age: 42,
+          address: 'London No. 1 Lake Park',
+        },
+        {
+          key: '3',
+          name: 'Joe Black',
+          age: 32,
+          address: 'Sidney No. 1 Lake Park',
+        },
+        {
+          key: '4',
+          name: 'Disabled User',
+          age: 99,
+          address: 'Sidney No. 1 Lake Park',
+        },
+      ];
+      this.state = {
+        dataSource: [...this.raw],
+        modalVisible: false,
+        columns: [
+          {
+            title: 'Name',
+            dataIndex: 'name',
+            render: text => <a href="javascript:;">{text}</a>,
+          },
+          {
+            title: 'Age',
+            dataIndex: 'age',
+          },
+          {
+            title: 'Address',
+            dataIndex: 'address',
+          },
+          {
+            title: 'Operation',
+            render: (text, record) => (
+              <div>
+                <Button icon={<IconDelete />} onClick={() => this.removeRecord(record.key)} />
+                <Button onClick={() => this.toggleModal(true)}>编辑</Button>
+              </div>
+            ),
+          },
+        ],
+      };
+    }
 
-                if (idx > -1) {
-                    dataSource.splice(idx, 1);
-                    this.setState({
-                        dataSource,
-                    });
-                }
-            }
-        }
+    removeRecord(key) {
+      let dataSource = [...this.state.dataSource];
 
-        resetData() {
-            let dataSource = [...this.raw];
-            this.setState({
-                dataSource,
-            });
-        }
+      if (key != null) {
+        let idx = dataSource.findIndex(data => data.key === key); // console.log(key, dataSource, idx);
 
-        toggleModal = modalVisible => {
-            this.setState({
-                modalVisible,
-            });
-        };
-        renderModalContent = () => {
-            const { modalVisible } = this.state;
-            return (
-                <Modal
-                    visible={modalVisible}
-                    onCancel={() => this.toggleModal(false)}
-                    onOk={() => this.toggleModal(false)}
-                >
-                    <p>This is a modal with customized styles.</p>
-                    <p>More content...</p>
-                    <Popover
-                        content={
-                            <div>
-                                <Button>按钮1</Button>
-                                <Button>按钮2</Button>
-                            </div>
-                        }
-                    >
-                        <Button>hover</Button>
-                    </Popover>
-                </Modal>
-            );
-        };
-
-        render() {
-            let { columns, dataSource } = this.state;
-            return (
-                <>
-                    <Button onClick={() => this.resetData()}>Reset</Button>
-                    <Table columns={columns} dataSource={dataSource} pagination={false} />
-                    {this.renderModalContent()}
-                </>
-            );
+        if (idx > -1) {
+          dataSource.splice(idx, 1);
+          this.setState({
+            dataSource,
+          });
         }
+      }
     }
 
-    return <TableApp />;
-});
+    resetData() {
+      let dataSource = [...this.raw];
+      this.setState({
+        dataSource,
+      });
+    }
 
-const ScrollDemo = function ScrollDemo(props = {}) {
-    const tops = [
-        ['topLeft', 'TL'],
-        ['top', 'Top'],
-        ['topRight', 'TR'],
-    ];
-    const lefts = [
-        ['leftTop', 'LT'],
-        ['left', 'Left'],
-        ['leftBottom', 'LB'],
-    ];
-    const rights = [
-        ['rightTop', 'RT'],
-        ['right', 'Right'],
-        ['rightBottom', 'RB'],
-    ];
-    const bottoms = [
-        ['bottomLeft', 'BL'],
-        ['bottom', 'Bottom'],
-        ['bottomRight', 'BR'],
-    ];
-    const { tagstyle, ...restProps } = props;
-    return (
-        <div
-            style={{
-                paddingLeft: 40,
-            }}
+    toggleModal = modalVisible => {
+      this.setState({
+        modalVisible,
+      });
+    };
+    renderModalContent = () => {
+      const { modalVisible } = this.state;
+      return (
+        <Modal
+          visible={modalVisible}
+          onCancel={() => this.toggleModal(false)}
+          onOk={() => this.toggleModal(false)}
         >
-            <div
-                style={{
-                    marginLeft: 40,
-                    whiteSpace: 'nowrap',
-                }}
-            >
-                {tops.map((pos, index) => (
-                    <Popover
-                        content={
-                            <article>
-                                <p>hi bytedance</p>
-                                <p>hi bytedance</p>
-                            </article>
-                        }
-                        position={Array.isArray(pos) ? pos[0] : pos}
-                        key={index}
-                        trigger={'click'}
-                        {...restProps}
-                    >
-                        <Tag style={tagstyle}>{Array.isArray(pos) ? pos[1] : pos}</Tag>
-                    </Popover>
-                ))}
-            </div>
-            <div
-                style={{
-                    width: 40,
-                    float: 'left',
-                }}
-            >
-                {lefts.map((pos, index) => (
-                    <Popover
-                        content={
-                            <article>
-                                <p>hi bytedance</p>
-                                <p>hi bytedance</p>
-                            </article>
-                        }
-                        position={Array.isArray(pos) ? pos[0] : pos}
-                        key={index}
-                        trigger={'click'}
-                        {...restProps}
-                    >
-                        <Tag style={tagstyle}>{Array.isArray(pos) ? pos[1] : pos}</Tag>
-                    </Popover>
-                ))}
-            </div>
-            <div
-                style={{
-                    width: 40,
-                    marginLeft: 180,
-                }}
-            >
-                {rights.map((pos, index) => (
-                    <Popover
-                        content={
-                            <article>
-                                <p>hi bytedance</p>
-                                <p>hi bytedance</p>
-                            </article>
-                        }
-                        position={Array.isArray(pos) ? pos[0] : pos}
-                        key={index}
-                        trigger={'click'}
-                        {...restProps}
-                    >
-                        <Tag style={tagstyle}>{Array.isArray(pos) ? pos[1] : pos}</Tag>
-                    </Popover>
-                ))}
-            </div>
-            <div
-                style={{
-                    marginLeft: 40,
-                    clear: 'both',
-                    whiteSpace: 'nowrap',
-                }}
-            >
-                {bottoms.map((pos, index) => (
-                    <Popover
-                        content={
-                            <article>
-                                <p>hi bytedance</p>
-                                <p>hi bytedance</p>
-                            </article>
-                        }
-                        position={Array.isArray(pos) ? pos[0] : pos}
-                        key={index}
-                        trigger={'click'}
-                        {...restProps}
-                    >
-                        <Tag style={tagstyle}>{Array.isArray(pos) ? pos[1] : pos}</Tag>
-                    </Popover>
-                ))}
-            </div>
-        </div>
-    );
-};
+          <p>This is a modal with customized styles.</p>
+          <p>More content...</p>
+          <Popover
+            content={
+              <div>
+                <Button>按钮1</Button>
+                <Button>按钮2</Button>
+              </div>
+            }
+          >
+            <Button>hover</Button>
+          </Popover>
+        </Modal>
+      );
+    };
 
-stories.add('scroll popover', () => {
-    return (
+    render() {
+      let { columns, dataSource } = this.state;
+      return (
         <>
-            <div id="wrapper">
-                <div
-                    style={{
-                        height: '200vh',
-                        width: '200vw',
-                        padding: 50,
-                    }}
-                >
-                    滚动到下面
-                </div>
-            </div>
-            <div
-                style={{
-                    padding: 1200,
-                }}
-            >
-                <ScrollDemo
-                    content={
-                        <article
-                            style={{
-                                padding: 12,
-                            }}
-                        >
-                            <p>hi bytedance</p>
-                            <p>hi bytedance</p>
-                        </article>
-                    }
-                />
-            </div>
+          <Button onClick={() => this.resetData()}>Reset</Button>
+          <Table columns={columns} dataSource={dataSource} pagination={false} />
+          {this.renderModalContent()}
         </>
-    );
-});
-stories.add('with arrow', () => (
-    <div>
-        <div
-            style={{
-                padding: 120,
-            }}
-        >
-            <ScrollDemo showArrow />
-        </div>
-        <div
-            style={{
-                padding: 120,
-            }}
-        >
-            <ScrollDemo
-                showArrow
-                tagstyle={{
-                    minHeight: 80,
-                    minWidth: 120,
-                }}
-            />
-        </div>
-        <div
-            style={{
-                padding: 120,
-            }}
-        >
-            <ScrollDemo
-                showArrow
-                tagstyle={{
-                    minHeight: 80,
-                    minWidth: 120,
-                }}
-                style={{
-                    backgroundColor: 'green',
-                }}
-            />
-        </div>
+      );
+    }
+  }
+
+  return <TableApp />;
+};
+
+const ScrollDemo = function ScrollDemo(props = {}) {
+  const tops = [
+    ['topLeft', 'TL'],
+    ['top', 'Top'],
+    ['topRight', 'TR'],
+  ];
+  const lefts = [
+    ['leftTop', 'LT'],
+    ['left', 'Left'],
+    ['leftBottom', 'LB'],
+  ];
+  const rights = [
+    ['rightTop', 'RT'],
+    ['right', 'Right'],
+    ['rightBottom', 'RB'],
+  ];
+  const bottoms = [
+    ['bottomLeft', 'BL'],
+    ['bottom', 'Bottom'],
+    ['bottomRight', 'BR'],
+  ];
+  const { tagstyle, ...restProps } = props;
+  return (
+    <div
+      style={{
+        paddingLeft: 40,
+      }}
+    >
+      <div
+        style={{
+          marginLeft: 40,
+          whiteSpace: 'nowrap',
+        }}
+      >
+        {tops.map((pos, index) => (
+          <Popover
+            content={
+              <article>
+                <p>hi bytedance</p>
+                <p>hi bytedance</p>
+              </article>
+            }
+            position={Array.isArray(pos) ? pos[0] : pos}
+            key={index}
+            trigger={'click'}
+            {...restProps}
+          >
+            <Tag style={tagstyle}>{Array.isArray(pos) ? pos[1] : pos}</Tag>
+          </Popover>
+        ))}
+      </div>
+      <div
+        style={{
+          width: 40,
+          float: 'left',
+        }}
+      >
+        {lefts.map((pos, index) => (
+          <Popover
+            content={
+              <article>
+                <p>hi bytedance</p>
+                <p>hi bytedance</p>
+              </article>
+            }
+            position={Array.isArray(pos) ? pos[0] : pos}
+            key={index}
+            trigger={'click'}
+            {...restProps}
+          >
+            <Tag style={tagstyle}>{Array.isArray(pos) ? pos[1] : pos}</Tag>
+          </Popover>
+        ))}
+      </div>
+      <div
+        style={{
+          width: 40,
+          marginLeft: 180,
+        }}
+      >
+        {rights.map((pos, index) => (
+          <Popover
+            content={
+              <article>
+                <p>hi bytedance</p>
+                <p>hi bytedance</p>
+              </article>
+            }
+            position={Array.isArray(pos) ? pos[0] : pos}
+            key={index}
+            trigger={'click'}
+            {...restProps}
+          >
+            <Tag style={tagstyle}>{Array.isArray(pos) ? pos[1] : pos}</Tag>
+          </Popover>
+        ))}
+      </div>
+      <div
+        style={{
+          marginLeft: 40,
+          clear: 'both',
+          whiteSpace: 'nowrap',
+        }}
+      >
+        {bottoms.map((pos, index) => (
+          <Popover
+            content={
+              <article>
+                <p>hi bytedance</p>
+                <p>hi bytedance</p>
+              </article>
+            }
+            position={Array.isArray(pos) ? pos[0] : pos}
+            key={index}
+            trigger={'click'}
+            {...restProps}
+          >
+            <Tag style={tagstyle}>{Array.isArray(pos) ? pos[1] : pos}</Tag>
+          </Popover>
+        ))}
+      </div>
     </div>
-));
-stories.add('no content', () => (
-    <div>
-        <div
-            style={{
-                padding: 50,
-            }}
-        >
-            <ScrollDemo content={<div></div>} />
-        </div>
-        <div
-            style={{
-                padding: 50,
-            }}
-        >
-            <ScrollDemo showArrow content={''} />
-        </div>
+  );
+};
+
+export const ScrollPopover = () => {
+  return (
+    <>
+      <div id="wrapper">
         <div
-            style={{
-                padding: 50,
-            }}
+          style={{
+            height: '200vh',
+            width: '200vw',
+            padding: 50,
+          }}
         >
-            <ScrollDemo
-                showArrow
-                content={''}
-                tagstyle={{
-                    height: 80,
-                    minWidth: 100,
-                }}
-                style={{
-                    padding: 20,
-                }}
-            />
+          滚动到下面
         </div>
+      </div>
+      <div
+        style={{
+          padding: 1200,
+        }}
+      >
+        <ScrollDemo
+          content={
+            <article
+              style={{
+                padding: 12,
+              }}
+            >
+              <p>hi bytedance</p>
+              <p>hi bytedance</p>
+            </article>
+          }
+        />
+      </div>
+    </>
+  );
+};
+
+ScrollPopover.story = {
+  name: 'scroll popover',
+};
+
+export const WithArrow = () => (
+  <div>
+    <div
+      style={{
+        padding: 120,
+      }}
+    >
+      <ScrollDemo showArrow />
+    </div>
+    <div
+      style={{
+        padding: 120,
+      }}
+    >
+      <ScrollDemo
+        showArrow
+        tagstyle={{
+          minHeight: 80,
+          minWidth: 120,
+        }}
+      />
     </div>
-));
-stories.add('select in popover', () => (
     <div
+      style={{
+        padding: 120,
+      }}
+    >
+      <ScrollDemo
+        showArrow
+        tagstyle={{
+          minHeight: 80,
+          minWidth: 120,
+        }}
         style={{
-            padding: 50,
+          backgroundColor: 'green',
         }}
+      />
+    </div>
+  </div>
+);
+
+WithArrow.story = {
+  name: 'with arrow',
+};
+
+export const NoContent = () => (
+  <div>
+    <div
+      style={{
+        padding: 50,
+      }}
+    >
+      <ScrollDemo content={<div></div>} />
+    </div>
+    <div
+      style={{
+        padding: 50,
+      }}
+    >
+      <ScrollDemo showArrow content={''} />
+    </div>
+    <div
+      style={{
+        padding: 50,
+      }}
     >
-        <SelectInPopover />
+      <ScrollDemo
+        showArrow
+        content={''}
+        tagstyle={{
+          height: 80,
+          minWidth: 100,
+        }}
+        style={{
+          padding: 20,
+        }}
+      />
     </div>
-));
-stories.add('close btn in popover', () => <BtnClose />);
-stories.add('popover float right', () => <PopRight />);
-stories.add(`nested popover`, () => <NestedPopover />);
-stories.add(`arrow point at center`, () => <ArrowPointAtCenter />);
+  </div>
+);
+
+NoContent.story = {
+  name: 'no content',
+};
+
+export const _SelectInPopover = () => (
+  <div
+    style={{
+      padding: 50,
+    }}
+  >
+    <SelectInPopover />
+  </div>
+);
+
+_SelectInPopover.story = {
+  name: 'select in popover',
+};
+
+export const CloseBtnInPopover = () => <BtnClose />;
+
+CloseBtnInPopover.story = {
+  name: 'close btn in popover',
+};
+
+export const PopoverFloatRight = () => <PopRight />;
+
+PopoverFloatRight.story = {
+  name: 'popover float right',
+};
+
+export const NestedPopoverDemo = () => <NestedPopover />;
+NestedPopoverDemo.story = {
+  name: 'nested popover'
+}
+
+export const ArrowPointAtCenterDemo = () => <ArrowPointAtCenter />;
+ArrowPointAtCenterDemo.story = {
+  name: 'arrow point at center'
+}

+ 68 - 47
packages/semi-ui/progress/_story/progress.stories.js

@@ -1,50 +1,71 @@
 import React, { useState } from 'react';
-import { storiesOf } from '@storybook/react';
 import { Progress, IconButton } from '../../index';
 
-const stories = storiesOf('Progress', module);
-
-stories.add('progress', () => (
-    <div style={{ width: 200 }}>
-        {/* <Progress percent={10} style= {{ height: 10 }}/> */}
-        <Progress percent={25} />
-        <Progress percent={50} />
-        <Progress percent={80} />
-    </div>
-));
-
-stories.add('vertical', () => (
-    <div style={{ height: 200 }}>
-        <Progress percent={10} direction="vertical" style={{ width: 10 }} />
-        <Progress percent={25} direction="vertical" />
-        <Progress percent={50} direction="vertical" />
-        <Progress percent={80} direction="vertical" />
-    </div>
-));
-
-stories.add('circle progress', () => (
-    <React.Fragment>
-        <Progress percent={10} type="circle" />
-        <Progress percent={25} type="circle" />
-        <Progress percent={50} type="circle" />
-        <Progress percent={80} type="circle" />
-    </React.Fragment>
-));
-
-stories.add('circle progress small', () => (
-    <React.Fragment>
-        <Progress percent={10} type="circle" size="small" />
-        <Progress percent={25} type="circle" size="small" />
-        <Progress percent={50} type="circle" size="small" />
-        <Progress percent={80} type="circle" size="small" />
-    </React.Fragment>
-));
-
-stories.add('progress showInfo', () => (
-    <div style={{ width: 200 }}>
-        {/* <Progress percent={10} style= {{ height: 10 }}/> */}
-        <Progress percent={25} showInfo />
-        <Progress percent={50} showInfo />
-        <Progress percent={80} showInfo />
-    </div>
-));
+export default {
+  title: 'Progress'
+}
+
+export const _Progress = () => (
+  <div style={{ width: 200 }}>
+    {/* <Progress percent={10} style= {{ height: 10 }}/> */}
+    <Progress percent={25} />
+    <Progress percent={50} />
+    <Progress percent={80} />
+  </div>
+);
+
+_Progress.story = {
+  name: 'progress',
+};
+
+export const Vertical = () => (
+  <div style={{ height: 200 }}>
+    <Progress percent={10} direction="vertical" style={{ width: 10 }} />
+    <Progress percent={25} direction="vertical" />
+    <Progress percent={50} direction="vertical" />
+    <Progress percent={80} direction="vertical" />
+  </div>
+);
+
+Vertical.story = {
+  name: 'vertical',
+};
+
+export const CircleProgress = () => (
+  <React.Fragment>
+    <Progress percent={10} type="circle" />
+    <Progress percent={25} type="circle" />
+    <Progress percent={50} type="circle" />
+    <Progress percent={80} type="circle" />
+  </React.Fragment>
+);
+
+CircleProgress.story = {
+  name: 'circle progress',
+};
+
+export const CircleProgressSmall = () => (
+  <React.Fragment>
+    <Progress percent={10} type="circle" size="small" />
+    <Progress percent={25} type="circle" size="small" />
+    <Progress percent={50} type="circle" size="small" />
+    <Progress percent={80} type="circle" size="small" />
+  </React.Fragment>
+);
+
+CircleProgressSmall.story = {
+  name: 'circle progress small',
+};
+
+export const ProgressShowInfo = () => (
+  <div style={{ width: 200 }}>
+    {/* <Progress percent={10} style= {{ height: 10 }}/> */}
+    <Progress percent={25} showInfo />
+    <Progress percent={50} showInfo />
+    <Progress percent={80} showInfo />
+  </div>
+);
+
+ProgressShowInfo.story = {
+  name: 'progress showInfo',
+};

+ 812 - 634
packages/semi-ui/radio/_story/radio.stories.js

@@ -1,5 +1,4 @@
 import React, { useState } from 'react';
-import { storiesOf } from '@storybook/react';
 import Button from '../../button';
 import Space from '../../space';
 
@@ -7,673 +6,852 @@ import { Radio, RadioGroup } from '../../index';
 import { Row, Col } from '../../grid';
 import './radio.scss';
 
-const stories = storiesOf('Radio', module);
+export default {
+  title: 'Radio'
+}
 
-// stories.addDecorator(withKnobs);;
+export const _Radio = () => {
+  let cssStyle = {
+    width: '200px',
+  };
+  return (
+    <div style={cssStyle}>
+      <Radio value="1">
+        Experts say the abandonment of book reading may have some unappealing consequences for
+        cognition. “People are clearly reading fewer books now than they used to, and that has to
+        have a cost because we know book reading is very good cognitive exercise,” says Ken Pugh,
+        director of research at the Yale-affiliated Haskins Laboratories, which examines the
+        importance of spoken and written language.
+      </Radio>
+    </div>
+  );
+};
 
-stories.add('radio', () => {
-    let cssStyle = {
-        width: '200px',
-    };
-    return (
-        <div style={cssStyle}>
-            <Radio value="1">
-                Experts say the abandonment of book reading may have some unappealing consequences for cognition.
-                “People are clearly reading fewer books now than they used to, and that has to have a cost because we
-                know book reading is very good cognitive exercise,” says Ken Pugh, director of research at the
-                Yale-affiliated Haskins Laboratories, which examines the importance of spoken and written language.
-            </Radio>
-        </div>
-    );
-});
+_Radio.story = {
+  name: 'radio',
+};
 
-stories.add('radio with extra', () => {
-    return (
-        <>
-            <Radio value="1" extra="这是辅助的文本,同厂辅助文本会更长一些,甚至还可能换行">
-                示例文本
-            </Radio>
-            <Radio style={{ width: 200 }} value="1" extra="这是辅助的文本,同厂辅助文本会更长一些,甚至还可能换行">
-                示例文本
-            </Radio>
-        </>
-    );
-});
-stories.add('radio checked', () => {
-    return (
-        <div>
-            {'受控的checked = true'}
-            <Radio value="1" checked>
-                111
-            </Radio>
-            <br />
-            {'受控的checked = false'}
-            <Radio value="1" checked={false}>
-                111
-            </Radio>
-            <br />
-            {'不受控的defaultChecked = true'}
-            <Radio value="1" defaultChecked={true}>
-                111
-            </Radio>
-            <br />
-            {'不受控的defaultChecked = false'}
-            <Radio value="1" defaultChecked={false}>
-                111
-            </Radio>
-        </div>
-    );
-});
+export const RadioWithExtra = () => {
+  return (
+    <>
+      <Radio value="1" extra="这是辅助的文本,同厂辅助文本会更长一些,甚至还可能换行">
+        示例文本
+      </Radio>
+      <Radio
+        style={{ width: 200 }}
+        value="1"
+        extra="这是辅助的文本,同厂辅助文本会更长一些,甚至还可能换行"
+      >
+        示例文本
+      </Radio>
+    </>
+  );
+};
 
-stories.add('radio disabled', () => {
-    return (
-        <div>
-            <Radio value="1" checked disabled>
-                111
-            </Radio>
-            <Radio value="1" disabled>
-                111
-            </Radio>
-        </div>
-    );
-});
+RadioWithExtra.story = {
+  name: 'radio with extra',
+};
 
-class RadioControl extends React.Component {
-    state = {
-        checked: true,
-        disabled: false,
-    };
+export const RadioChecked = () => {
+  return (
+    <div>
+      {'受控的checked = true'}
+      <Radio value="1" checked>
+        111
+      </Radio>
+      <br />
+      {'受控的checked = false'}
+      <Radio value="1" checked={false}>
+        111
+      </Radio>
+      <br />
+      {'不受控的defaultChecked = true'}
+      <Radio value="1" defaultChecked={true}>
+        111
+      </Radio>
+      <br />
+      {'不受控的defaultChecked = false'}
+      <Radio value="1" defaultChecked={false}>
+        111
+      </Radio>
+    </div>
+  );
+};
 
-    toggleChecked = () => {
-        this.setState({ checked: !this.state.checked });
-    };
+RadioChecked.story = {
+  name: 'radio checked',
+};
 
-    toggleDisable = () => {
-        this.setState({ disabled: !this.state.disabled });
-    };
+export const RadioDisabled = () => {
+  return (
+    <div>
+      <Radio value="1" checked disabled>
+        111
+      </Radio>
+      <Radio value="1" disabled>
+        111
+      </Radio>
+    </div>
+  );
+};
 
-    onChange = e => {
-        console.log('checked = ', e.target.checked);
-        this.setState({
-            checked: e.target.checked,
-        });
-    };
+RadioDisabled.story = {
+  name: 'radio disabled',
+};
 
-    render() {
-        const label = `${this.state.checked ? 'Checked' : 'Unchecked'}-${this.state.disabled ? 'Disabled' : 'Enabled'}`;
-        return (
-            <div>
-                <p style={{ marginBottom: '20px' }}>
-                    <Radio checked={this.state.checked} disabled={this.state.disabled} onChange={this.onChange}>
-                        {label}
-                    </Radio>
-                </p>
-                <p>
-                    <Button type="primary" size="small" onClick={this.toggleChecked}>
-                        {!this.state.checked ? 'Check' : 'Uncheck'}
-                    </Button>
-                    <Button style={{ marginLeft: '10px' }} type="primary" size="small" onClick={this.toggleDisable}>
-                        {!this.state.disabled ? 'Disable' : 'Enable'}
-                    </Button>
-                </p>
-            </div>
-        );
-    }
+class RadioControl extends React.Component {
+  state = {
+    checked: true,
+    disabled: false,
+  };
+
+  toggleChecked = () => {
+    this.setState({ checked: !this.state.checked });
+  };
+
+  toggleDisable = () => {
+    this.setState({ disabled: !this.state.disabled });
+  };
+
+  onChange = e => {
+    console.log('checked = ', e.target.checked);
+    this.setState({
+      checked: e.target.checked,
+    });
+  };
+
+  render() {
+    const label = `${this.state.checked ? 'Checked' : 'Unchecked'}-${
+      this.state.disabled ? 'Disabled' : 'Enabled'
+    }`;
+    return (
+      <div>
+        <p style={{ marginBottom: '20px' }}>
+          <Radio
+            checked={this.state.checked}
+            disabled={this.state.disabled}
+            onChange={this.onChange}
+          >
+            {label}
+          </Radio>
+        </p>
+        <p>
+          <Button type="primary" size="small" onClick={this.toggleChecked}>
+            {!this.state.checked ? 'Check' : 'Uncheck'}
+          </Button>
+          <Button
+            style={{ marginLeft: '10px' }}
+            type="primary"
+            size="small"
+            onClick={this.toggleDisable}
+          >
+            {!this.state.disabled ? 'Disable' : 'Enable'}
+          </Button>
+        </p>
+      </div>
+    );
+  }
 }
 
-stories.add('Radio controlled disabled & checked', () => <RadioControl />);
+export const RadioControlledDisabledChecked = () => <RadioControl />;
 
-const RadioGroup1 = () => {
-    const [state, setChecked] = useState('1');
-    console.log(state);
+RadioControlledDisabledChecked.story = {
+  name: 'Radio controlled disabled & checked',
+};
 
-    return (
-        <div>
-            <Radio.Group
-                value={state}
-                onChange={evt => {
-                    setChecked(evt.target.value);
-                }}
-            >
-                <Radio value="1" grouped>
-                    1
-                </Radio>
-                <Radio value="2" grouped>
-                    2
-                </Radio>
-            </Radio.Group>
-            点击触发state变化,state变化触发展示变化
-            <Radio.Group
-                value={state}
-                onChange={evt => {
-                    setChecked(evt.target.value);
-                }}
-            >
-                <Radio value="2" grouped>
-                    2
-                </Radio>
-                <Radio value="1" grouped>
-                    1
-                </Radio>
-            </Radio.Group>
-        </div>
-    );
+const RadioGroup1 = () => {
+  const [state, setChecked] = useState('1');
+  console.log(state);
+
+  return (
+    <div>
+      <Radio.Group
+        value={state}
+        onChange={evt => {
+          setChecked(evt.target.value);
+        }}
+      >
+        <Radio value="1" grouped>
+          1
+        </Radio>
+        <Radio value="2" grouped>
+          2
+        </Radio>
+      </Radio.Group>
+      点击触发state变化,state变化触发展示变化
+      <Radio.Group
+        value={state}
+        onChange={evt => {
+          setChecked(evt.target.value);
+        }}
+      >
+        <Radio value="2" grouped>
+          2
+        </Radio>
+        <Radio value="1" grouped>
+          1
+        </Radio>
+      </Radio.Group>
+    </div>
+  );
 };
 class RadioWithControled extends React.Component {
-    constructor(props) {
-        super(props);
-        this.state = {
-            value: false,
-        };
-    }
-
-    onChange(value) {
-        this.setState({
-            value: value.target.value,
-        });
-    }
-
-    render() {
-        return (
-            <RadioGroup name="apple" value={this.state.value} onChange={this.onChange.bind(this)}>
-                <Radio value={true}>111</Radio>
-                <Radio value={false}>222</Radio>
-            </RadioGroup>
-        );
-    }
-}
-stories.add('radio group', () => {
-    let onChange = data => {
-        console.log('change', data);
+  constructor(props) {
+    super(props);
+    this.state = {
+      value: false,
     };
+  }
 
-    return (
-        <div>
-            value=1
-            <RadioGroup name="pie" value="1" onChange={onChange}>
-                <Radio value="1">111</Radio>
-                <Radio value="2">222</Radio>
-            </RadioGroup>
-            <br />
-            defaultValue=1
-            <RadioGroup name="pie" defaultValue="1" onChange={onChange}>
-                <Radio value="1">111</Radio>
-                <Radio value="2">222</Radio>
-            </RadioGroup>
-            <br />
-            value+onchange
-            <RadioWithControled />
-            <br />
-            联动
-            <RadioGroup1 />
-        </div>
-    );
-});
+  onChange(value) {
+    this.setState({
+      value: value.target.value,
+    });
+  }
 
-stories.add('radio with vertical', () => {
+  render() {
     return (
-        <Radio.Group>
-            <Radio value="A" displayMode="vertical">
-                无限长的一串字The Storybook webapp UI can be customised with this addon. It can be used to change the
-                header, show/hide various UI elements and to enable full-screen mode by default.
-            </Radio>
-            <Radio value="C" displayMode="vertical">
-                C
-            </Radio>
-            <Radio value="D" displayMode="vertical">
-                D
-            </Radio>
-            <Radio value="E" displayMode="vertical">
-                E
-            </Radio>
-        </Radio.Group>
+      <RadioGroup name="apple" value={this.state.value} onChange={this.onChange.bind(this)}>
+        <Radio value={true}>111</Radio>
+        <Radio value={false}>222</Radio>
+      </RadioGroup>
     );
-});
-
-stories.add('radio group with options', () => {
-    const plainOptions = ['Apple', 'Pear', 'Orange'];
-    const options = [
-        { label: 'Apple', value: 'Apple' },
-        { label: 'Pear', value: 'Pear' },
-        { label: 'Orange', value: 'Orange', disabled: true },
-    ];
-    const optionsWithDisabled = [
-        { label: 'Apple', value: 'Apple' },
-        { label: 'Pear', value: 'Pear' },
-        { label: 'Orange', value: 'Orange', disabled: false },
-    ];
-
-    function onChange(event) {
-        console.log(event);
-    }
+  }
+}
 
-    return (
-        <div>
-            <RadioGroup name="apple" options={plainOptions} onChange={onChange} />
-            <RadioGroup name="apple" options={options} onChange={onChange} />
-            <RadioGroup name="apple" disabled options={optionsWithDisabled} onChange={onChange} />
-        </div>
-    );
-});
+export const _RadioGroup = () => {
+  let onChange = data => {
+    console.log('change', data);
+  };
+
+  return (
+    <div>
+      value=1
+      <RadioGroup name="pie" value="1" onChange={onChange}>
+        <Radio value="1">111</Radio>
+        <Radio value="2">222</Radio>
+      </RadioGroup>
+      <br />
+      defaultValue=1
+      <RadioGroup name="pie" defaultValue="1" onChange={onChange}>
+        <Radio value="1">111</Radio>
+        <Radio value="2">222</Radio>
+      </RadioGroup>
+      <br />
+      value+onchange
+      <RadioWithControled />
+      <br />
+      联动
+      <RadioGroup1 />
+    </div>
+  );
+};
+
+_RadioGroup.story = {
+  name: 'radio group',
+};
+
+export const RadioWithVertical = () => {
+  return (
+    <Radio.Group>
+      <Radio value="A" displayMode="vertical">
+        无限长的一串字The Storybook webapp UI can be customised with this addon. It can be used to
+        change the header, show/hide various UI elements and to enable full-screen mode by default.
+      </Radio>
+      <Radio value="C" displayMode="vertical">
+        C
+      </Radio>
+      <Radio value="D" displayMode="vertical">
+        D
+      </Radio>
+      <Radio value="E" displayMode="vertical">
+        E
+      </Radio>
+    </Radio.Group>
+  );
+};
+
+RadioWithVertical.story = {
+  name: 'radio with vertical',
+};
+
+export const RadioGroupWithOptions = () => {
+  const plainOptions = ['Apple', 'Pear', 'Orange'];
+  const options = [
+    { label: 'Apple', value: 'Apple' },
+    { label: 'Pear', value: 'Pear' },
+    { label: 'Orange', value: 'Orange', disabled: true },
+  ];
+  const optionsWithDisabled = [
+    { label: 'Apple', value: 'Apple' },
+    { label: 'Pear', value: 'Pear' },
+    { label: 'Orange', value: 'Orange', disabled: false },
+  ];
+
+  function onChange(event) {
+    console.log(event);
+  }
+
+  return (
+    <div>
+      <RadioGroup name="apple" options={plainOptions} onChange={onChange} />
+      <RadioGroup name="apple" options={options} onChange={onChange} />
+      <RadioGroup name="apple" disabled options={optionsWithDisabled} onChange={onChange} />
+    </div>
+  );
+};
+
+RadioGroupWithOptions.story = {
+  name: 'radio group with options',
+};
 
 const RadioWithAdvancedMode = () => {
-    const [state, setChecked] = useState([true]);
+  const [state, setChecked] = useState([true]);
+
+  return (
+    <div>
+      <Radio
+        checked={state}
+        mode="advanced"
+        onChange={e => {
+          console.log(e);
+          setChecked(e.target.checked);
+        }}
+      >
+        111
+      </Radio>
+    </div>
+  );
+};
+export const _RadioWithAdvancedMode = () => <RadioWithAdvancedMode />;
 
-    return (
-        <div>
-            <Radio
-                checked={state}
-                mode="advanced"
-                onChange={e => {
-                    console.log(e);
-                    setChecked(e.target.checked);
-                }}
-            >
-                111
-            </Radio>
+_RadioWithAdvancedMode.story = {
+  name: 'radio with advanced mode',
+};
+
+export const RadioGroupWithAdvancedMode = () => {
+  function onChange(evt) {
+    console.log(evt);
+  }
+
+  return (
+    <>
+      <RadioGroup mode="advanced" onChange={onChange}>
+        <Radio value="1">111</Radio>
+        <Radio value="2">222</Radio>
+        <Radio value="3">333</Radio>
+      </RadioGroup>
+      <br />
+      <br />
+      <RadioGroup mode="advanced" onChange={onChange} direction="horizontal">
+        <div className="block-radio-wrapper">
+          <Radio value="1">111</Radio>
         </div>
-    );
+        <div className="block-radio-wrapper">
+          <Radio value="2">222</Radio>
+        </div>
+        <div className="block-radio-wrapper">
+          <Radio value="3">333</Radio>
+        </div>
+      </RadioGroup>
+    </>
+  );
 };
-stories.add('radio with advanced mode', () => <RadioWithAdvancedMode />);
 
-stories.add('radio group with advanced mode', () => {
-    function onChange(evt) {
-        console.log(evt);
-    }
+RadioGroupWithAdvancedMode.story = {
+  name: 'radio group with advanced mode',
+};
 
-    return (
-        <>
-            <RadioGroup mode="advanced" onChange={onChange}>
-                <Radio value="1">111</Radio>
-                <Radio value="2">222</Radio>
-                <Radio value="3">333</Radio>
-            </RadioGroup>
-            <br />
-            <br />
-            <RadioGroup mode="advanced" onChange={onChange} direction='horizontal'>
-                <div className='block-radio-wrapper'>
-                    <Radio value="1">111</Radio>
-                </div>
-                <div className='block-radio-wrapper'>
-                    <Radio value="2">222</Radio>
-                </div>
-                <div className='block-radio-wrapper'>
-                    <Radio value="3">333</Radio>
-                </div>
-            </RadioGroup>
-        </>
-    );
-});
+export const RadioGrid = () => {
+  return (
+    <Radio.Group style={{ width: '100%' }}>
+      <Row>
+        <Col span={8}>
+          <Radio value="A">
+            无限长的一串字The Storybook webapp UI can be customised with this addon. It can be used
+            to change the header, show/hide various UI elements and to enable full-screen mode by
+            default.
+          </Radio>
+        </Col>
+        <Col span={8}>
+          <Radio value="B">B</Radio>
+        </Col>
+        <Col span={8}>
+          <Radio value="C">C</Radio>
+        </Col>
+        <Col span={8}>
+          <Radio value="D">D</Radio>
+        </Col>
+        <Col span={8}>
+          <Radio value="E">E</Radio>
+        </Col>
+      </Row>
+    </Radio.Group>
+  );
+};
 
-stories.add('radio + grid', () => {
-    return (
-        <Radio.Group style={{ width: '100%' }}>
-            <Row>
-                <Col span={8}>
-                    <Radio value="A">
-                        无限长的一串字The Storybook webapp UI can be customised with this addon. It can be used to
-                        change the header, show/hide various UI elements and to enable full-screen mode by default.
-                    </Radio>
-                </Col>
-                <Col span={8}>
-                    <Radio value="B">B</Radio>
-                </Col>
-                <Col span={8}>
-                    <Radio value="C">C</Radio>
-                </Col>
-                <Col span={8}>
-                    <Radio value="D">D</Radio>
-                </Col>
-                <Col span={8}>
-                    <Radio value="E">E</Radio>
-                </Col>
-            </Row>
-        </Radio.Group>
-    );
-});
-
-stories.add(`dynamic radioGroup`, () => {
-    const Demo = () => {
-        const [value, setValue] = useState(1);
-        const onChange = e => {
-            console.log('radio checked', e.target.value);
-
-            setValue(e.target.value);
-        };
-        return (
-            <RadioGroup onChange={onChange} value={value}>
-                {value !== 4 ? <Radio value={1}>A</Radio> : null}
-                <Radio value={2}>B</Radio>
-                <Radio value={3}>C</Radio>
-                <Radio value={4}>D</Radio>
-            </RadioGroup>
-        );
-    };
+RadioGrid.story = {
+  name: 'radio + grid',
+};
 
-    return <Demo />;
-});
-
-stories.add(`radioGroup button style`, () => {
-    const Demo = () => {
-        const [value1, setValue1] = useState(1);
-        const [value2, setValue2] = useState(2);
-        const [value3, setValue3] = useState(3);
-        const onChange1 = e => {
-            setValue1(e.target.value);
-        };
-        const onChange2 = e => {
-            setValue2(e.target.value);
-        };
-        const onChange3 = e => {
-            setValue3(e.target.value);
-        };
-        return (
-            <Space vertical spacing='loose' align='start'>
-                <RadioGroup type='button' buttonSize='small' onChange={onChange1} value={value1}>
-                    <Radio value={1}>semi</Radio>
-                    <Radio value={2}>pipixia</Radio>
-                    <Radio value={3}>hotsoon</Radio>
-                    <Radio value={4}>toutiao</Radio>
-                </RadioGroup>
-                <RadioGroup type='button' buttonSize='middle' onChange={onChange2} value={value2}>
-                    <Radio value={1}>semi</Radio>
-                    <Radio value={2}>pipixia</Radio>
-                    <Radio value={3}>hotsoon</Radio>
-                    <Radio value={4}>toutiao</Radio>
-                </RadioGroup>
-                <RadioGroup type='button' buttonSize='large' onChange={onChange3} value={value3}>
-                    <Radio value={1}>semi</Radio>
-                    <Radio value={2}>pipixia</Radio>
-                    <Radio value={3}>hotsoon</Radio>
-                    <Radio value={4}>toutiao</Radio>
-                </RadioGroup>
-            </Space>
-        );
+export const DynamicRadioGroup = () => {
+  const Demo = () => {
+    const [value, setValue] = useState(1);
+    const onChange = e => {
+      console.log('radio checked', e.target.value);
+
+      setValue(e.target.value);
     };
+    return (
+      <RadioGroup onChange={onChange} value={value}>
+        {value !== 4 ? <Radio value={1}>A</Radio> : null}
+        <Radio value={2}>B</Radio>
+        <Radio value={3}>C</Radio>
+        <Radio value={4}>D</Radio>
+      </RadioGroup>
+    );
+  };
 
-    return <Demo />;
-});
+  return <Demo />;
+};
+DynamicRadioGroup.style = {
+  name: 'dynamic radioGroup'
+};
 
-stories.add(`radioGroup card style`, () => (
-    <>
-        <div>常见情况</div>
-        <RadioGroup type='card' defaultValue={1}>
-            <Radio value={1} extra='Semi Design' style={{ width: 280 }}>
-                多选框标题
-            </Radio>
-            <Radio value={2} extra='Semi Design' style={{ width: 280 }}>
-                多选框标题
-            </Radio>
-            <Radio value={3} extra='Semi Design' style={{ width: 280 }}>
-                多选框标题
-            </Radio>
-        </RadioGroup>
-        <br />
-        <br />
-        <div>radio disabled</div>
-        <RadioGroup type='card' defaultValue={1}>
-            <Radio value={1} disabled extra='Semi Design' style={{ width: 280 }}>
-                多选框标题
-            </Radio>
-            <Radio value={2} extra='Semi Design' style={{ width: 280 }}>
-                多选框标题
-            </Radio>
-            <Radio value={3} extra='Semi Design' style={{ width: 280 }}>
-                多选框标题
-            </Radio>
-        </RadioGroup>
-        <br />
-        <br />
-        <div>radioGroup disabled</div>
-        <RadioGroup type='card' disabled defaultValue={1}>
-            <Radio value={1} extra='Semi Design' style={{ width: 280 }}>
-                多选框标题
-            </Radio>
-            <Radio value={2} extra='Semi Design' style={{ width: 280 }}>
-                多选框标题
-            </Radio>
-            <Radio value={3} extra='Semi Design' style={{ width: 280 }}>
-                多选框标题
-            </Radio>
-        </RadioGroup>
-        <br />
-        <br />
-        <div>文字很长,并且没有设置宽度,因此换行显示</div>
-        <RadioGroup type='card' defaultValue={1}>
-            <Radio value={1} extra='Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统'>
-                多选框标题
-            </Radio>
-            <Radio value={2} extra='Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统'>
-                多选框标题
-            </Radio>
-            <Radio value={3} extra='Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统'>
-                多选框标题
-            </Radio>
-        </RadioGroup>
-        <br />
-        <br />
-        <div>设置了width=180</div>
-        <RadioGroup type='card' defaultValue={1}>
-            <Radio value={1} extra='Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统' style={{ width: 180 }}>
-                多选框标题
-            </Radio>
-            <Radio value={2} extra='Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统' style={{ width: 180 }}>
-                多选框标题
-            </Radio>
-            <Radio value={3} extra='Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统' style={{ width: 180 }}>
-                多选框标题
-            </Radio>
-        </RadioGroup>
-        <br />
-        <br />
-        <div>没有extra,width=180</div>
-        <RadioGroup type='card' defaultValue={1}>
-            <Radio value={1} style={{ width: 180 }}>
-                多选框标题
-            </Radio>
-            <Radio value={2} style={{ width: 180 }}>
-                多选框标题
-            </Radio>
-            <Radio value={3} style={{ width: 180 }}>
-                多选框标题
-            </Radio>
-        </RadioGroup>
-        <br />
-        <br />
-        <div>没有标题,width=380</div>
-        <RadioGroup type='card' defaultValue={1}>
-            <Radio value={1} extra='Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统' style={{ width: 380 }}>
-            </Radio>
-            <Radio value={2} extra='Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统' style={{ width: 380 }}>
-            </Radio>
-            <Radio value={3} extra='Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统' style={{ width: 380 }}>
-            </Radio>
-        </RadioGroup>
-        <br />
-        <br />
-        <hr />
-        <div>下面是垂直的情况:</div>
-        <div>常见情况</div>
-        <RadioGroup direction='vertical' type='card' defaultValue={1}>
-            <Radio value={1} extra='Semi Design' style={{ width: 280 }}>
-                多选框标题
-            </Radio>
-            <Radio value={2} extra='Semi Design' style={{ width: 280 }}>
-                多选框标题
-            </Radio>
-            <Radio value={3} extra='Semi Design' style={{ width: 280 }}>
-                多选框标题
-            </Radio>
+export const RadioGroupButtonStyle = () => {
+  const Demo = () => {
+    const [value1, setValue1] = useState(1);
+    const [value2, setValue2] = useState(2);
+    const [value3, setValue3] = useState(3);
+    const onChange1 = e => {
+      setValue1(e.target.value);
+    };
+    const onChange2 = e => {
+      setValue2(e.target.value);
+    };
+    const onChange3 = e => {
+      setValue3(e.target.value);
+    };
+    return (
+      <Space vertical spacing="loose" align="start">
+        <RadioGroup type="button" buttonSize="small" onChange={onChange1} value={value1}>
+          <Radio value={1}>semi</Radio>
+          <Radio value={2}>pipixia</Radio>
+          <Radio value={3}>hotsoon</Radio>
+          <Radio value={4}>toutiao</Radio>
         </RadioGroup>
-        <br />
-        <br />
-        <div>没有设置宽度</div>
-        <RadioGroup direction='vertical' type='card' defaultValue={1}>
-            <Radio value={1} extra='Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统'>
-                多选框标题
-            </Radio>
-            <Radio value={2} extra='Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统'>
-                多选框标题
-            </Radio>
-            <Radio value={3} extra='Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统'>
-                多选框标题
-            </Radio>
+        <RadioGroup type="button" buttonSize="middle" onChange={onChange2} value={value2}>
+          <Radio value={1}>semi</Radio>
+          <Radio value={2}>pipixia</Radio>
+          <Radio value={3}>hotsoon</Radio>
+          <Radio value={4}>toutiao</Radio>
         </RadioGroup>
-        <br />
-        <br />
-        <div>设置了width=380</div>
-        <RadioGroup direction='vertical' type='card' defaultValue={1}>
-            <Radio value={1} extra='Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统' style={{ width: 380 }}>
-                多选框标题
-            </Radio>
-            <Radio value={2} extra='Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统' style={{ width: 380 }}>
-                多选框标题
-            </Radio>
-            <Radio value={3} extra='Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统' style={{ width: 380 }}>
-                多选框标题
-            </Radio>
+        <RadioGroup type="button" buttonSize="large" onChange={onChange3} value={value3}>
+          <Radio value={1}>semi</Radio>
+          <Radio value={2}>pipixia</Radio>
+          <Radio value={3}>hotsoon</Radio>
+          <Radio value={4}>toutiao</Radio>
         </RadioGroup>
-    </>
-));
+      </Space>
+    );
+  };
 
-stories.add(`radioGroup pureCard style`, () => (
-    <>
-        <div>常见情况</div>
-        <RadioGroup type='pureCard' defaultValue={1}>
-            <Radio value={1} extra='Semi Design' style={{ width: 280 }}>
-                多选框标题
-            </Radio>
-            <Radio value={2} extra='Semi Design' style={{ width: 280 }}>
-                多选框标题
-            </Radio>
-            <Radio value={3} extra='Semi Design' style={{ width: 280 }}>
-                多选框标题
-            </Radio>
-        </RadioGroup>
-        <br />
-        <br />
-        <div>radio disabled</div>
-        <RadioGroup type='pureCard' defaultValue={1}>
-            <Radio value={1} disabled extra='Semi Design' style={{ width: 280 }}>
-                多选框标题
-            </Radio>
-            <Radio value={2} extra='Semi Design' style={{ width: 280 }}>
-                多选框标题
-            </Radio>
-            <Radio value={3} extra='Semi Design' style={{ width: 280 }}>
-                多选框标题
-            </Radio>
-        </RadioGroup>
-        <br />
-        <br />
-        <div>radioGroup disabled</div>
-        <RadioGroup type='pureCard' disabled defaultValue={1}>
-            <Radio value={1} extra='Semi Design' style={{ width: 280 }}>
-                多选框标题
-            </Radio>
-            <Radio value={2} extra='Semi Design' style={{ width: 280 }}>
-                多选框标题
-            </Radio>
-            <Radio value={3} extra='Semi Design' style={{ width: 280 }}>
-                多选框标题
-            </Radio>
-        </RadioGroup>
-        <br />
-        <br />
-        <div>文字很长,并且没有设置宽度,因此换行显示</div>
-        <RadioGroup type='pureCard' defaultValue={1}>
-            <Radio value={1} extra='Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统'>
-                多选框标题
-            </Radio>
-            <Radio value={2} extra='Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统'>
-                多选框标题
-            </Radio>
-            <Radio value={3} extra='Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统'>
-                多选框标题
-            </Radio>
-        </RadioGroup>
-        <br />
-        <br />
-        <div>设置了width=180</div>
-        <RadioGroup type='pureCard' defaultValue={1}>
-            <Radio value={1} extra='Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统' style={{ width: 180 }}>
-                多选框标题
-            </Radio>
-            <Radio value={2} extra='Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统' style={{ width: 180 }}>
-                多选框标题
-            </Radio>
-            <Radio value={3} extra='Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统' style={{ width: 180 }}>
-                多选框标题
-            </Radio>
-        </RadioGroup>
-        <br />
-        <br />
-        <div>没有extra,width=180</div>
-        <RadioGroup type='pureCard' defaultValue={1}>
-            <Radio value={1} style={{ width: 180 }}>
-                多选框标题
-            </Radio>
-            <Radio value={2} style={{ width: 180 }}>
-                多选框标题
-            </Radio>
-            <Radio value={3} style={{ width: 180 }}>
-                多选框标题
-            </Radio>
-        </RadioGroup>
-        <br />
-        <br />
-        <div>没有标题,width=380</div>
-        <RadioGroup type='pureCard' defaultValue={1}>
-            <Radio value={1} extra='Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统' style={{ width: 380 }}>
-            </Radio>
-            <Radio value={2} extra='Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统' style={{ width: 380 }}>
-            </Radio>
-            <Radio value={3} extra='Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统' style={{ width: 380 }}>
-            </Radio>
-        </RadioGroup>
-        <br />
-        <br />
-        <hr />
-        <div>下面是垂直的情况:</div>
-        <div>常见情况</div>
-        <RadioGroup direction='vertical' type='pureCard' defaultValue={1}>
-            <Radio value={1} extra='Semi Design' style={{ width: 280 }}>
-                多选框标题
-            </Radio>
-            <Radio value={2} extra='Semi Design' style={{ width: 280 }}>
-                多选框标题
-            </Radio>
-            <Radio value={3} extra='Semi Design' style={{ width: 280 }}>
-                多选框标题
-            </Radio>
-        </RadioGroup>
-        <br />
-        <br />
-        <div>没有设置宽度</div>
-        <RadioGroup direction='vertical' type='pureCard' defaultValue={1}>
-            <Radio value={1} extra='Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统'>
-                多选框标题
-            </Radio>
-            <Radio value={2} extra='Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统'>
-                多选框标题
-            </Radio>
-            <Radio value={3} extra='Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统'>
-                多选框标题
-            </Radio>
-        </RadioGroup>
-        <br />
-        <br />
-        <div>设置了width=380</div>
-        <RadioGroup direction='vertical' type='pureCard' defaultValue={1}>
-            <Radio value={1} extra='Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统' style={{ width: 380 }}>
-                多选框标题
-            </Radio>
-            <Radio value={2} extra='Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统' style={{ width: 380 }}>
-                多选框标题
-            </Radio>
-            <Radio value={3} extra='Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统' style={{ width: 380 }}>
-                多选框标题
-            </Radio>
-        </RadioGroup>
-    </>
-));
+  return <Demo />;
+};
+RadioGroupButtonStyle.story = {
+  name: 'radioGroup button style'
+};
+
+
+export const RadioGroupCardStyle = () => (
+  <>
+    <div>常见情况</div>
+    <RadioGroup type="card" defaultValue={1}>
+      <Radio value={1} extra="Semi Design" style={{ width: 280 }}>
+        多选框标题
+      </Radio>
+      <Radio value={2} extra="Semi Design" style={{ width: 280 }}>
+        多选框标题
+      </Radio>
+      <Radio value={3} extra="Semi Design" style={{ width: 280 }}>
+        多选框标题
+      </Radio>
+    </RadioGroup>
+    <br />
+    <br />
+    <div>radio disabled</div>
+    <RadioGroup type="card" defaultValue={1}>
+      <Radio value={1} disabled extra="Semi Design" style={{ width: 280 }}>
+        多选框标题
+      </Radio>
+      <Radio value={2} extra="Semi Design" style={{ width: 280 }}>
+        多选框标题
+      </Radio>
+      <Radio value={3} extra="Semi Design" style={{ width: 280 }}>
+        多选框标题
+      </Radio>
+    </RadioGroup>
+    <br />
+    <br />
+    <div>radioGroup disabled</div>
+    <RadioGroup type="card" disabled defaultValue={1}>
+      <Radio value={1} extra="Semi Design" style={{ width: 280 }}>
+        多选框标题
+      </Radio>
+      <Radio value={2} extra="Semi Design" style={{ width: 280 }}>
+        多选框标题
+      </Radio>
+      <Radio value={3} extra="Semi Design" style={{ width: 280 }}>
+        多选框标题
+      </Radio>
+    </RadioGroup>
+    <br />
+    <br />
+    <div>文字很长,并且没有设置宽度,因此换行显示</div>
+    <RadioGroup type="card" defaultValue={1}>
+      <Radio
+        value={1}
+        extra="Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统"
+      >
+        多选框标题
+      </Radio>
+      <Radio
+        value={2}
+        extra="Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统"
+      >
+        多选框标题
+      </Radio>
+      <Radio
+        value={3}
+        extra="Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统"
+      >
+        多选框标题
+      </Radio>
+    </RadioGroup>
+    <br />
+    <br />
+    <div>设置了width=180</div>
+    <RadioGroup type="card" defaultValue={1}>
+      <Radio
+        value={1}
+        extra="Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统"
+        style={{ width: 180 }}
+      >
+        多选框标题
+      </Radio>
+      <Radio
+        value={2}
+        extra="Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统"
+        style={{ width: 180 }}
+      >
+        多选框标题
+      </Radio>
+      <Radio
+        value={3}
+        extra="Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统"
+        style={{ width: 180 }}
+      >
+        多选框标题
+      </Radio>
+    </RadioGroup>
+    <br />
+    <br />
+    <div>没有extra,width=180</div>
+    <RadioGroup type="card" defaultValue={1}>
+      <Radio value={1} style={{ width: 180 }}>
+        多选框标题
+      </Radio>
+      <Radio value={2} style={{ width: 180 }}>
+        多选框标题
+      </Radio>
+      <Radio value={3} style={{ width: 180 }}>
+        多选框标题
+      </Radio>
+    </RadioGroup>
+    <br />
+    <br />
+    <div>没有标题,width=380</div>
+    <RadioGroup type="card" defaultValue={1}>
+      <Radio
+        value={1}
+        extra="Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统"
+        style={{ width: 380 }}
+      ></Radio>
+      <Radio
+        value={2}
+        extra="Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统"
+        style={{ width: 380 }}
+      ></Radio>
+      <Radio
+        value={3}
+        extra="Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统"
+        style={{ width: 380 }}
+      ></Radio>
+    </RadioGroup>
+    <br />
+    <br />
+    <hr />
+    <div>下面是垂直的情况:</div>
+    <div>常见情况</div>
+    <RadioGroup direction="vertical" type="card" defaultValue={1}>
+      <Radio value={1} extra="Semi Design" style={{ width: 280 }}>
+        多选框标题
+      </Radio>
+      <Radio value={2} extra="Semi Design" style={{ width: 280 }}>
+        多选框标题
+      </Radio>
+      <Radio value={3} extra="Semi Design" style={{ width: 280 }}>
+        多选框标题
+      </Radio>
+    </RadioGroup>
+    <br />
+    <br />
+    <div>没有设置宽度</div>
+    <RadioGroup direction="vertical" type="card" defaultValue={1}>
+      <Radio
+        value={1}
+        extra="Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统"
+      >
+        多选框标题
+      </Radio>
+      <Radio
+        value={2}
+        extra="Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统"
+      >
+        多选框标题
+      </Radio>
+      <Radio
+        value={3}
+        extra="Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统"
+      >
+        多选框标题
+      </Radio>
+    </RadioGroup>
+    <br />
+    <br />
+    <div>设置了width=380</div>
+    <RadioGroup direction="vertical" type="card" defaultValue={1}>
+      <Radio
+        value={1}
+        extra="Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统"
+        style={{ width: 380 }}
+      >
+        多选框标题
+      </Radio>
+      <Radio
+        value={2}
+        extra="Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统"
+        style={{ width: 380 }}
+      >
+        多选框标题
+      </Radio>
+      <Radio
+        value={3}
+        extra="Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统"
+        style={{ width: 380 }}
+      >
+        多选框标题
+      </Radio>
+    </RadioGroup>
+  </>
+);
+
+RadioGroupCardStyle.story = {
+  name: 'radioGroup card style'
+}
+
+export const RadioGroupPureCardStyle = () => (
+  <>
+    <div>常见情况</div>
+    <RadioGroup type="pureCard" defaultValue={1}>
+      <Radio value={1} extra="Semi Design" style={{ width: 280 }}>
+        多选框标题
+      </Radio>
+      <Radio value={2} extra="Semi Design" style={{ width: 280 }}>
+        多选框标题
+      </Radio>
+      <Radio value={3} extra="Semi Design" style={{ width: 280 }}>
+        多选框标题
+      </Radio>
+    </RadioGroup>
+    <br />
+    <br />
+    <div>radio disabled</div>
+    <RadioGroup type="pureCard" defaultValue={1}>
+      <Radio value={1} disabled extra="Semi Design" style={{ width: 280 }}>
+        多选框标题
+      </Radio>
+      <Radio value={2} extra="Semi Design" style={{ width: 280 }}>
+        多选框标题
+      </Radio>
+      <Radio value={3} extra="Semi Design" style={{ width: 280 }}>
+        多选框标题
+      </Radio>
+    </RadioGroup>
+    <br />
+    <br />
+    <div>radioGroup disabled</div>
+    <RadioGroup type="pureCard" disabled defaultValue={1}>
+      <Radio value={1} extra="Semi Design" style={{ width: 280 }}>
+        多选框标题
+      </Radio>
+      <Radio value={2} extra="Semi Design" style={{ width: 280 }}>
+        多选框标题
+      </Radio>
+      <Radio value={3} extra="Semi Design" style={{ width: 280 }}>
+        多选框标题
+      </Radio>
+    </RadioGroup>
+    <br />
+    <br />
+    <div>文字很长,并且没有设置宽度,因此换行显示</div>
+    <RadioGroup type="pureCard" defaultValue={1}>
+      <Radio
+        value={1}
+        extra="Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统"
+      >
+        多选框标题
+      </Radio>
+      <Radio
+        value={2}
+        extra="Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统"
+      >
+        多选框标题
+      </Radio>
+      <Radio
+        value={3}
+        extra="Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统"
+      >
+        多选框标题
+      </Radio>
+    </RadioGroup>
+    <br />
+    <br />
+    <div>设置了width=180</div>
+    <RadioGroup type="pureCard" defaultValue={1}>
+      <Radio
+        value={1}
+        extra="Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统"
+        style={{ width: 180 }}
+      >
+        多选框标题
+      </Radio>
+      <Radio
+        value={2}
+        extra="Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统"
+        style={{ width: 180 }}
+      >
+        多选框标题
+      </Radio>
+      <Radio
+        value={3}
+        extra="Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统"
+        style={{ width: 180 }}
+      >
+        多选框标题
+      </Radio>
+    </RadioGroup>
+    <br />
+    <br />
+    <div>没有extra,width=180</div>
+    <RadioGroup type="pureCard" defaultValue={1}>
+      <Radio value={1} style={{ width: 180 }}>
+        多选框标题
+      </Radio>
+      <Radio value={2} style={{ width: 180 }}>
+        多选框标题
+      </Radio>
+      <Radio value={3} style={{ width: 180 }}>
+        多选框标题
+      </Radio>
+    </RadioGroup>
+    <br />
+    <br />
+    <div>没有标题,width=380</div>
+    <RadioGroup type="pureCard" defaultValue={1}>
+      <Radio
+        value={1}
+        extra="Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统"
+        style={{ width: 380 }}
+      ></Radio>
+      <Radio
+        value={2}
+        extra="Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统"
+        style={{ width: 380 }}
+      ></Radio>
+      <Radio
+        value={3}
+        extra="Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统"
+        style={{ width: 380 }}
+      ></Radio>
+    </RadioGroup>
+    <br />
+    <br />
+    <hr />
+    <div>下面是垂直的情况:</div>
+    <div>常见情况</div>
+    <RadioGroup direction="vertical" type="pureCard" defaultValue={1}>
+      <Radio value={1} extra="Semi Design" style={{ width: 280 }}>
+        多选框标题
+      </Radio>
+      <Radio value={2} extra="Semi Design" style={{ width: 280 }}>
+        多选框标题
+      </Radio>
+      <Radio value={3} extra="Semi Design" style={{ width: 280 }}>
+        多选框标题
+      </Radio>
+    </RadioGroup>
+    <br />
+    <br />
+    <div>没有设置宽度</div>
+    <RadioGroup direction="vertical" type="pureCard" defaultValue={1}>
+      <Radio
+        value={1}
+        extra="Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统"
+      >
+        多选框标题
+      </Radio>
+      <Radio
+        value={2}
+        extra="Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统"
+      >
+        多选框标题
+      </Radio>
+      <Radio
+        value={3}
+        extra="Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统"
+      >
+        多选框标题
+      </Radio>
+    </RadioGroup>
+    <br />
+    <br />
+    <div>设置了width=380</div>
+    <RadioGroup direction="vertical" type="pureCard" defaultValue={1}>
+      <Radio
+        value={1}
+        extra="Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统"
+        style={{ width: 380 }}
+      >
+        多选框标题
+      </Radio>
+      <Radio
+        value={2}
+        extra="Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统"
+        style={{ width: 380 }}
+      >
+        多选框标题
+      </Radio>
+      <Radio
+        value={3}
+        extra="Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统"
+        style={{ width: 380 }}
+      >
+        多选框标题
+      </Radio>
+    </RadioGroup>
+  </>
+);
+RadioGroupPureCardStyle.story = {
+  name: 'radioGroup pureCard style'
+}

+ 83 - 69
packages/semi-ui/rating/_story/rating.stories.js

@@ -1,83 +1,97 @@
 import React from 'react';
-import { storiesOf } from '@storybook/react'; // import { withKnobs, text, boolean } from '@storybook/addon-knobs';
-
-import withPropsCombinations from 'react-storybook-addon-props-combinations';
 import Rating from '../index';
-import Icon from '../../icons';
 import { IconLikeHeart } from '@douyinfe/semi-icons';
-const stories = storiesOf('Rating', module); // stories.addDecorator(withKnobs);;
 
-stories.add('Rating', () => (
-    <div style={{display: 'flex'}}>
-        <div style={{ width: '50%' }}>
-            <h5>default</h5>
-            <Rating />
-            <br />
-            <h5>allowHalf</h5>
-            <Rating allowHalf />
-            <br />
-            <h5>disabled</h5>
-            <Rating disabled defaultValue={4} />
-            <br />
-            <h5>allowClear = false</h5>
-            <Rating allowClear={false} />
-            <br />
-            <h5>character</h5>
-            <Rating character={<IconLikeHeart />} />
-            <br />
-            <Rating character={'好'} defaultValue={2} disabled />
-        </div>
-        <div style={{ width: '50%' }}>
-            <br />
-            <h5>tooltips</h5>
-            <Rating tooltips={['terrible', 'bad', 'normal', 'good', 'wonderful']} />
-            <br />
-            <h5>defaultValue</h5>
-            <Rating defaultValue={2} />
-            <h5>value</h5>
-            <Rating value={3} />
-            <br />
-            <h5>onHoverChange</h5>
-            <Rating onHoverChange={e => console.log(e)} />
-            <h5>size</h5>
-            <Rating size='small' defaultValue={2} />
-            <Rating size='large' defaultValue={2} />
-        </div>
+export default {
+  title: 'Rating',
+  parameters: {
+    chromatic: { disableSnapshot: true },
+  },
+}
+
+export const _Rating = () => (
+  <div style={{ display: 'flex' }}>
+    <div style={{ width: '50%' }}>
+      <h5>default</h5>
+      <Rating />
+      <br />
+      <h5>allowHalf</h5>
+      <Rating allowHalf />
+      <br />
+      <h5>disabled</h5>
+      <Rating disabled defaultValue={4} />
+      <br />
+      <h5>allowClear = false</h5>
+      <Rating allowClear={false} />
+      <br />
+      <h5>character</h5>
+      <Rating character={<IconLikeHeart />} />
+      <br />
+      <Rating character={'好'} defaultValue={2} disabled />
+    </div>
+    <div style={{ width: '50%' }}>
+      <br />
+      <h5>tooltips</h5>
+      <Rating tooltips={['terrible', 'bad', 'normal', 'good', 'wonderful']} />
+      <br />
+      <h5>defaultValue</h5>
+      <Rating defaultValue={2} />
+      <h5>value</h5>
+      <Rating value={3} />
+      <br />
+      <h5>onHoverChange</h5>
+      <Rating onHoverChange={e => console.log(e)} />
+      <h5>size</h5>
+      <Rating size="small" defaultValue={2} />
+      <Rating size="large" defaultValue={2} />
     </div>
-));
+  </div>
+);
+
+_Rating.parameters = {
+  chromatic: { disableSnapshot: false },
+};
 
 class Demo extends React.Component {
-    constructor(props) {
-        super();
-        this.state = {
-            value: 0,
-        };
-        this.handleChange = this.handleChange.bind(this);
-    }
+  constructor(props) {
+    super();
+    this.state = {
+      value: 0,
+    };
+    this.handleChange = this.handleChange.bind(this);
+  }
 
-    handleChange(value) {
-        this.setState({
-            value,
-        });
-    }
+  handleChange(value) {
+    this.setState({
+      value,
+    });
+  }
 
-    render() {
-        const { value } = this.state;
-        const desc = ['terrible', 'bad', 'normal', 'good', 'wonderful'];
-        return (
-            <div>
-                <span>How was the help you received: {value ? <span>{desc[value - 1]}</span> : ''}</span>
-                <br />
-                <Rating tooltips={desc} onChange={this.handleChange} value={value} />
-            </div>
-        );
-    }
+  render() {
+    const { value } = this.state;
+    const desc = ['terrible', 'bad', 'normal', 'good', 'wonderful'];
+    return (
+      <div>
+        <span>How was the help you received: {value ? <span>{desc[value - 1]}</span> : ''}</span>
+        <br />
+        <Rating tooltips={desc} onChange={this.handleChange} value={value} />
+      </div>
+    );
+  }
 }
 
-stories.add('tooltip Rating', () => <Demo />);
+export const TooltipRating = () => <Demo />;
+
+TooltipRating.story = {
+  name: 'tooltip Rating',
+};
 
 const KeyDownDemo = () => {
-    return <Rating onKeyDown={event => console.log(event) }/>
-}
+  return <Rating onKeyDown={event => console.log(event)} />;
+};
+
+export const Keydown = () => <KeyDownDemo />;
 
-stories.add('keydown', () => <KeyDownDemo />);
+Keydown.story = {
+  name: 'keydown',
+};

+ 20 - 9
packages/semi-ui/scrollList/_story/scrolllist.stories.js

@@ -1,15 +1,26 @@
 import React from 'react';
-import { storiesOf } from '@storybook/react';
-import ScrollList from '../index';
-import ScrollItem from '../scrollItem';
-import Button from '../../button';
 import WheelListDemo from './WheelList';
 import ScrollListDemo from './ScrollList';
 
-const stories = storiesOf('scrollList', module);
 
-stories.add('ScrollList simple', () => {
-    return <ScrollListDemo />;
-});
+export default {
+  title: 'ScrollList'
+}
 
-stories.add('wheel list demo', () => <WheelListDemo />);
+export const ScrollListSimple = () => {
+  return <ScrollListDemo />;
+};
+
+ScrollListSimple.story = {
+  name: 'ScrollList simple',
+};
+
+ScrollListSimple.parameters = {
+  chromatic: { disableSnapshot: true },
+}
+
+export const _WheelListDemo = () => <WheelListDemo />;
+
+_WheelListDemo.story = {
+  name: 'wheel list demo',
+};

+ 2620 - 2418
packages/semi-ui/select/_story/select.stories.js

@@ -1,7 +1,5 @@
-import React, { useState, useRef } from 'react';
-import { storiesOf } from '@storybook/react'; // import { withKnobs, text, boolean } from '@storybook/addon-knobs';
+import React, { useState, useRef, useEffect } from 'react';
 
-import withPropsCombinations from 'react-storybook-addon-props-combinations';
 import './select.scss';
 import { Input, Select, Button, Icon, Avatar, Checkbox, Form, withField, Space } from '../../index';
 import CustomTrigger from './CustomTrigger';
@@ -9,2648 +7,2852 @@ import classNames from 'classnames';
 import { getHighLightTextHTML } from '../../_utils/index';
 const Option = Select.Option;
 import { IconSearch, IconGift } from '@douyinfe/semi-icons';
-const stories = storiesOf('Select', module); // stories.addDecorator(withKnobs);;
 
-let Test = () => {
-    let [options, setOptions] = useState([1, 2, 3, 4]);
-
-    function add() {
-        let newOptions = Array.from(
-            {
-                length: Math.floor(Math.random() * 10),
-            },
-            (v, i) => i + 1
-        );
-        setOptions(newOptions);
-    }
+export default {
+  title: 'Select',
+  parameters: {
+    chromatic: { disableSnapshot: true },
+  },
+}
 
-    let style = {
-        width: 150,
-        margin: 20,
-    };
-    let slotStyle = {
-        backgroundColor: 'whitesmoke',
-        height: '40px',
-        display: 'flex',
-        justifyContent: 'center',
-        alignItems: 'center',
-        borderRadius: '0 0 6px 6px',
-    };
-    let outSlotStyle = {
-        backgroundColor: 'whitesmoke',
-        height: '29px',
-        display: 'flex',
-        justifyContent: 'center',
-        alignItems: 'center',
-        cursor: 'pointer',
-    };
+let Test = () => {
+  let [options, setOptions] = useState([1, 2, 3, 4]);
+
+  function add() {
+    let newOptions = Array.from(
+      {
+        length: Math.floor(Math.random() * 10),
+      },
+      (v, i) => i + 1
+    );
+    setOptions(newOptions);
+  }
+
+  let style = {
+    width: 150,
+    margin: 20,
+  };
+  let slotStyle = {
+    backgroundColor: 'whitesmoke',
+    height: '40px',
+    display: 'flex',
+    justifyContent: 'center',
+    alignItems: 'center',
+    borderRadius: '0 0 6px 6px',
+  };
+  let outSlotStyle = {
+    backgroundColor: 'whitesmoke',
+    height: '29px',
+    display: 'flex',
+    justifyContent: 'center',
+    alignItems: 'center',
+    cursor: 'pointer',
+  };
 
-    const click = e => {};
+  const click = e => {};
 
-    let outSlotNode = (
-        <div onClick={e => click(e)}>
-            <Checkbox>sendLarkNotification</Checkbox>
-            <div>
-                <Button theme="solid">confirm</Button>
-            </div>
-        </div>
-    );
-    return (
-        <>
-            <Select
-                style={style}
-                dropdownClassName="test-dropdown"
-                dropdownStyle={{
-                    width: 150,
-                }}
-                filter
-                placeholder="fefe"
-                position="rightTop"
-                innerBottomSlot={
-                    <div style={slotStyle}>
-                        <Button
-                            size="small"
-                            style={{
-                                margin: 0,
-                            }}
-                        >
-                            申请其他地区权限
-                        </Button>
-                    </div>
-                }
-            >
-                {options.map(option => (
-                    <Option value={option} key={option} className="fefe">
-                        {option}
-                    </Option>
-                ))}
-            </Select>
-            <Select
-                style={{
-                    marginTop: 20,
-                    width: 200,
-                }}
-                dropdownClassName="test-dropdown"
-                dropdownStyle={{
-                    width: 150,
-                }}
-                filter
-                placeholder="fefe"
-                position="rightTop"
-                outerBottomSlot={outSlotNode}
+  let outSlotNode = (
+    <div onClick={e => click(e)}>
+      <Checkbox>sendLarkNotification</Checkbox>
+      <div>
+        <Button theme="solid">confirm</Button>
+      </div>
+    </div>
+  );
+  return (
+    <>
+      <Select
+        style={style}
+        dropdownClassName="test-dropdown"
+        dropdownStyle={{
+          width: 150,
+        }}
+        filter
+        placeholder="fefe"
+        position="rightTop"
+        innerBottomSlot={
+          <div style={slotStyle}>
+            <Button
+              size="small"
+              style={{
+                margin: 0,
+              }}
             >
-                {options.map(option => (
-                    <Option value={option} key={option} className="fefe">
-                        {option}
-                    </Option>
-                ))}
-            </Select>
-        </>
-    );
+              申请其他地区权限
+            </Button>
+          </div>
+        }
+      >
+        {options.map(option => (
+          <Option value={option} key={option} className="fefe">
+            {option}
+          </Option>
+        ))}
+      </Select>
+      <Select
+        style={{
+          marginTop: 20,
+          width: 200,
+        }}
+        dropdownClassName="test-dropdown"
+        dropdownStyle={{
+          width: 150,
+        }}
+        filter
+        placeholder="fefe"
+        position="rightTop"
+        outerBottomSlot={outSlotNode}
+      >
+        {options.map(option => (
+          <Option value={option} key={option} className="fefe">
+            {option}
+          </Option>
+        ))}
+      </Select>
+    </>
+  );
 };
 
 const AutoFocusDemo = () => {
-    return (
-        <>
-            <Select
-                autoFocus
-                style={{
-                    width: 200,
-                }}
-                onFocus={() => console.log('onFocus')}
-                onBlur={() => console.log('onBlur')}
-            >
-                <Option value="abc">抖音</Option>
-                <Option value="hotsoon">火山</Option>
-                <Option value="pipixia">皮皮虾</Option>
-                <Option value="duoshan">多闪</Option>
-                <Option value="xigua">西瓜视频</Option>
-            </Select>
-            <div className="test-div">test-div</div>
-        </>
-    );
+  return (
+    <>
+      <Select
+        autoFocus
+        style={{
+          width: 200,
+        }}
+        onFocus={() => console.log('onFocus')}
+        onBlur={() => console.log('onBlur')}
+      >
+        <Option value="abc">抖音</Option>
+        <Option value="hotsoon">火山</Option>
+        <Option value="pipixia">皮皮虾</Option>
+        <Option value="duoshan">多闪</Option>
+        <Option value="xigua">西瓜视频</Option>
+      </Select>
+      <div className="test-div">test-div</div>
+    </>
+  );
 };
 
-stories.add('autoFocus', () => <AutoFocusDemo />);
-stories.add('innerBottommSlot / outerBottomSlot', () => <Test />);
-stories.add('innerTopSlot / outerTopSlot', () => {
-    const slot = <div>未找到应用?</div>;
-    return (
-        <div>
-            innerTopSlot
-            <div>
-                <Select
-                    innerTopSlot={slot}
-                    style={{
-                        width: 250,
-                    }}
-                    maxHeight={150}
-                >
-                    <Option value="abc">抖音</Option>
-                    <Option value="hotsoon">火山</Option>
-                    <Option value="pipixia">皮皮虾</Option>
-                    <Option value="duoshan">多闪</Option>
-                    <Option value="xigua">西瓜视频</Option>
-                </Select>
-            </div>
-            outerTopSlot
-            <div>
-                <Select
-                    outerTopSlot={slot}
-                    style={{
-                        width: 250,
-                    }}
-                    maxHeight={150}
-                >
-                    <Option value="abc">抖音</Option>
-                    <Option value="hotsoon">火山</Option>
-                    <Option value="pipixia">皮皮虾</Option>
-                    <Option value="duoshan">多闪</Option>
-                    <Option value="xigua">西瓜视频</Option>
-                </Select>
-            </div>
-        </div>
-    );
-});
-stories.add('一个Option,其他数组', () => (
-    <Select
-        defaultValue={'all'}
-        style={{
+export const AutoFocus = () => <AutoFocusDemo />;
+
+AutoFocus.story = {
+  name: 'autoFocus',
+};
+
+export const InnerBottomSlotOuterBottomSlot = () => <Test />;
+
+InnerBottomSlotOuterBottomSlot.story = {
+  name: 'innerBottomSlot / outerBottomSlot',
+};
+
+export const InnerTopSlotOuterTopSlot = () => {
+  const slot = <div>未找到应用?</div>;
+  return (
+    <div>
+      innerTopSlot
+      <div>
+        <Select
+          innerTopSlot={slot}
+          style={{
             width: 250,
-        }}
-    >
-        <Option value="all" key="all">
-            all
-        </Option>
-        {[1, 2, 3].map(item => (
-            <Option value={`type${item}`} key={item}>{`type${item}`}</Option>
-        ))}
-    </Select>
-));
+          }}
+          maxHeight={150}
+        >
+          <Option value="abc">抖音</Option>
+          <Option value="hotsoon">火山</Option>
+          <Option value="pipixia">皮皮虾</Option>
+          <Option value="duoshan">多闪</Option>
+          <Option value="xigua">西瓜视频</Option>
+        </Select>
+      </div>
+      outerTopSlot
+      <div>
+        <Select
+          outerTopSlot={slot}
+          style={{
+            width: 250,
+          }}
+          maxHeight={150}
+        >
+          <Option value="abc">抖音</Option>
+          <Option value="hotsoon">火山</Option>
+          <Option value="pipixia">皮皮虾</Option>
+          <Option value="duoshan">多闪</Option>
+          <Option value="xigua">西瓜视频</Option>
+        </Select>
+      </div>
+    </div>
+  );
+};
+
+InnerTopSlotOuterTopSlot.story = {
+  name: 'innerTopSlot / outerTopSlot',
+};
+
+export const OneOptionJsxWithOtherOptionArray = () => (
+  <Select
+    defaultValue={'all'}
+    style={{
+      width: 250,
+    }}
+  >
+    <Option value="all" key="all">
+      all
+    </Option>
+    {[1, 2, 3].map(item => (
+      <Option value={`type${item}`} key={item}>{`type${item}`}</Option>
+    ))}
+  </Select>
+);
+
+OneOptionJsxWithOtherOptionArray.story = {
+  name: 'one option jsx with other option array',
+};
+
 let options = [
-    {
-        value: 'all',
-        label: '全部',
-        otherKey: 'all semi',
-    },
-    {
-        value: 'abc',
-        label: '抖音',
-        otherKey: 'abc semi',
-    },
-    {
-        value: 'hotsoon',
-        label: '火山小视频',
-        otherKey: 'hostsoom semi',
-    },
-    {
-        value: 'pipixia',
-        label: '皮皮虾',
-        otherKey: 'pif',
-    },
-    {
-        value: 'toutiao',
-        label: '今日头条',
-        otherKey: 'toutiao semi',
-    },
-    {
-        value: 'rd',
-        label: 'rd',
-        otherKey: 'semi rd',
-    },
-    {
-        value: 'ued',
-        label: 'ued',
-        otherKey: 'semi ued',
-    },
-    {
-        value: 'ued',
-        label: 'japan',
-        otherKey: 'semi ued',
-    },
-    {
-        value: '+86',
-        label: '+86',
-        otherKey: 'semi',
-    },
+  {
+    value: 'all',
+    label: '全部',
+    otherKey: 'all semi',
+  },
+  {
+    value: 'abc',
+    label: '抖音',
+    otherKey: 'abc semi',
+  },
+  {
+    value: 'hotsoon',
+    label: '火山小视频',
+    otherKey: 'hostsoom semi',
+  },
+  {
+    value: 'pipixia',
+    label: '皮皮虾',
+    otherKey: 'pif',
+  },
+  {
+    value: 'toutiao',
+    label: '今日头条',
+    otherKey: 'toutiao semi',
+  },
+  {
+    value: 'rd',
+    label: 'rd',
+    otherKey: 'semi rd',
+  },
+  {
+    value: 'ued',
+    label: 'ued',
+    otherKey: 'semi ued',
+  },
+  {
+    value: 'ued',
+    label: 'japan',
+    otherKey: 'semi ued',
+  },
+  {
+    value: '+86',
+    label: '+86',
+    otherKey: 'semi',
+  },
 ];
 let longOptions = options.concat({
-    value: 'long',
-    label: 'Semi Design 是一个设计系统,它定义了一套中后台设计与前端基础组',
+  value: 'long',
+  label: 'Semi Design 是一个设计系统,它定义了一套中后台设计与前端基础组',
 });
-stories.add('select size', () => (
+
+export const SelectSize = () => (
+  <div
+    style={{
+      margin: 20,
+    }}
+  >
+    <h4>
+      使用方不设width时,下拉菜单根据内容自动适配宽度(不推荐这样使用,select的宽度会动态变化)
+    </h4>
+    <Select
+      defaultValue={'all'}
+      optionList={options}
+      style={{
+        margin: 10,
+      }}
+    ></Select>
+    <Select
+      defaultValue={'long'}
+      optionList={longOptions}
+      style={{
+        margin: 10,
+      }}
+    ></Select>
+    <Select
+      defaultValue={'abc'}
+      size="large"
+      optionList={options}
+      style={{
+        margin: 10,
+      }}
+    ></Select>
+    {/* <Select defaultValue={'+86'} size="large" optionList={options}  style={{margin: 10}}>
+    </Select> */}
+    <h4>通过style设width的</h4>
+    90px:{' '}
+    <Select
+      defaultValue={'all'}
+      style={{
+        width: 90,
+        marign: 10,
+      }}
+      optionList={options}
+    ></Select>
+    120px:{' '}
+    <Select
+      defaultValue={'all'}
+      style={{
+        width: 120,
+        margin: 10,
+      }}
+      optionList={options}
+    ></Select>
+    400px:{' '}
+    <Select
+      defaultValue={'all'}
+      style={{
+        width: 400,
+        margin: 10,
+      }}
+      optionList={options}
+    ></Select>
+    <br />
+    100%:{' '}
+    <Select
+      defaultValue={'all'}
+      style={{
+        width: '100%',
+        margin: 10,
+      }}
+      optionList={options}
+    ></Select>
+    <br />
+    <h4>通过css设width的</h4>
+    <Select defaultValue={'all'} className="test-width" optionList={options}></Select>
+    <br />
+    <h4>dropdownMatchSelectWidth</h4>
+    <p>当该项设为true时,下拉菜单最小宽度会等于Select宽度(默认为true)</p>
     <div
+      style={{
+        margin: 10,
+      }}
+    >
+      style方式指定90px:
+      <Select
+        defaultValue={'all'}
+        optionList={options}
+        dropdownMatchSelectWidth={true}
         style={{
-            margin: 20,
+          width: 90,
         }}
+      />
+    </div>
+    <div
+      style={{
+        margin: 10,
+      }}
     >
-        <h4>使用方不设width时,下拉菜单根据内容自动适配宽度(不推荐这样使用,select的宽度会动态变化)</h4>
-        <Select
-            defaultValue={'all'}
-            optionList={options}
-            style={{
-                margin: 10,
-            }}
-        ></Select>
-        <Select
-            defaultValue={'long'}
-            optionList={longOptions}
-            style={{
-                margin: 10,
-            }}
-        ></Select>
-        <Select
-            defaultValue={'abc'}
-            size="large"
-            optionList={options}
-            style={{
-                margin: 10,
-            }}
-        ></Select>
-        {/* <Select defaultValue={'+86'} size="large" optionList={options}  style={{margin: 10}}>
-    </Select> */}
-        <h4>通过style设width的</h4>
-        90px:{' '}
-        <Select
-            defaultValue={'all'}
-            style={{
-                width: 90,
-                marign: 10,
-            }}
-            optionList={options}
-        ></Select>
-        120px:{' '}
-        <Select
-            defaultValue={'all'}
-            style={{
-                width: 120,
-                margin: 10,
-            }}
-            optionList={options}
-        ></Select>
-        400px:{' '}
-        <Select
-            defaultValue={'all'}
-            style={{
-                width: 400,
-                margin: 10,
-            }}
-            optionList={options}
-        ></Select>
-        <br />
-        100%:{' '}
-        <Select
-            defaultValue={'all'}
-            style={{
-                width: '100%',
-                margin: 10,
-            }}
-            optionList={options}
-        ></Select>
-        <br />
-        <h4>通过css设width的</h4>
-        <Select defaultValue={'all'} className="test-width" optionList={options}></Select>
-        <br />
-        <h4>dropdownMatchSelectWidth</h4>
-        <p>当该项设为true时,下拉菜单最小宽度会等于Select宽度(默认为true)</p>
-        <div
-            style={{
-                margin: 10,
-            }}
-        >
-            style方式指定90px:
-            <Select
-                defaultValue={'all'}
-                optionList={options}
-                dropdownMatchSelectWidth={true}
-                style={{
-                    width: 90,
-                }}
-            />
-        </div>
-        <div
-            style={{
-                margin: 10,
-            }}
-        >
-            css方式声明130px:
-            <Select
-                defaultValue={'all'}
-                className="test-width"
-                optionList={options}
-                dropdownMatchSelectWidth={true}
-            ></Select>
-        </div>
-        <div>
-            <h4>需要强制下拉菜单与select同宽的时候</h4>
-            <p>通过dropdownStyle覆盖min-width,将其设成与select的width同样的值</p>
-            <Select
-                defaultValue={'all'}
-                style={{
-                    width: 300,
-                    margin: 10,
-                }}
-                dropdownStyle={{
-                    width: 300,
-                }}
-                optionList={options}
-            />
-        </div>
+      css方式声明130px:
+      <Select
+        defaultValue={'all'}
+        className="test-width"
+        optionList={options}
+        dropdownMatchSelectWidth={true}
+      ></Select>
     </div>
-));
-stories.add('with prefix / suffix / insetLabel, showClear, showArrow', () => (
-    <>
-        <h4>prefix & suffix</h4>
-        <Select
-            style={{
-                width: '250px',
-            }}
-            optionList={options}
-            prefix={<IconSearch />}
-            suffix={<IconGift></IconGift>}
-        ></Select>
-        <h4>insetLabel</h4>
-        <Select
-            style={{
-                width: '250px',
-            }}
-            optionList={options}
-            insetLabel={'业务线'}
-        ></Select>
-        <h4>showClear</h4>
-        <Select
-            style={{
-                width: '250px',
-            }}
-            optionList={options}
-            showClear
-        ></Select>
-        <h4>showArrow = false</h4>
-        <Select
-            style={{
-                width: '250px',
-            }}
-            optionList={options}
-            showArrow={false}
-        ></Select>
-
-        <h4>defaultValue是不存在的值</h4>
-        <Select
-            style={{
-                width: '250px',
-            }}
-            optionList={options}
-            defaultValue="+85"
-        ></Select>
-    </>
-));
-stories.add('with default selected', () => (
-    <Select
+    <div>
+      <h4>需要强制下拉菜单与select同宽的时候</h4>
+      <p>通过dropdownStyle覆盖min-width,将其设成与select的width同样的值</p>
+      <Select
+        defaultValue={'all'}
         style={{
-            width: '250px',
+          width: 300,
+          margin: 10,
         }}
-        defaultValue={1}
-    >
-        <Option value={1}>opt1</Option>
-        <Option value={2}>opt2</Option>
-        <Option value={3}>opt3</Option>
-        <Option value="4">opt4</Option>
-    </Select>
-));
-stories.add('with scrollbar', () => (
-    <Select
-        style={{
-            width: '250px',
+        dropdownStyle={{
+          width: 300,
         }}
-        defaultValue={1}
-    >
-        <Option value={1}>opt1</Option>
-        <Option value={2}>opt2</Option>
-        <Option value={3}>opt3</Option>
-        <Option value="4">opt4</Option>
-        <Option value={5}>opt5</Option>
-        <Option value={6}>opt6</Option>
-        <Option value={7}>opt7</Option>
-        <Option value="8">opt8</Option>
-        <Option value={9}>opt9</Option>
-        <Option value={10}>opt10dfsdfsdfdsfdsfsdf</Option>
-        <Option value={11}>opt11</Option>
-        <Option value="12">opt12jfldsjflsdjlfldjslfjhifsdfdsfdsffdsodsjlfhjl</Option>
-    </Select>
-));
+        optionList={options}
+      />
+    </div>
+  </div>
+);
 
-class Link extends React.Component {
-    get provinces() {
-        return ['Sichuan', 'Guangdong'];
-    }
+SelectSize.story = {
+  name: 'select size',
+};
 
-    get maps() {
-        return {
-            Sichuan: ['Chengdu', 'Dujiangyan'],
-            Guangdong: ['Guangzhou', 'Shenzhen', 'Dongguan'],
-        };
-    }
+export const WithPrefixSuffixInsetLabelShowClearShowArrow = () => (
+  <>
+    <h4>prefix & suffix</h4>
+    <Select
+      style={{
+        width: '250px',
+      }}
+      optionList={options}
+      prefix={<IconSearch />}
+      suffix={<IconGift></IconGift>}
+    ></Select>
+    <h4>insetLabel</h4>
+    <Select
+      style={{
+        width: '250px',
+      }}
+      optionList={options}
+      insetLabel={'业务线'}
+    ></Select>
+    <h4>showClear</h4>
+    <Select
+      style={{
+        width: '250px',
+      }}
+      optionList={options}
+      showClear
+    ></Select>
+    <h4>showArrow = false</h4>
+    <Select
+      style={{
+        width: '250px',
+      }}
+      optionList={options}
+      showArrow={false}
+    ></Select>
 
-    constructor() {
-        super();
-        this.state = {
-            provinces: this.provinces,
-            maps: this.maps,
-            citys: this.maps[this.provinces[0]],
-            city: this.maps[this.provinces[0]][0],
-        };
-        this.provinceChange = this.provinceChange.bind(this);
-        this.cityChange = this.cityChange.bind(this);
-    }
+    <h4>defaultValue是不存在的值</h4>
+    <Select
+      style={{
+        width: '250px',
+      }}
+      optionList={options}
+      defaultValue="+85"
+    ></Select>
+  </>
+);
 
-    provinceChange(newProvince) {
-        const { maps } = this.state;
-        this.setState({
-            citys: maps[newProvince],
-            city: maps[newProvince][0],
-        });
-    }
+WithPrefixSuffixInsetLabelShowClearShowArrow.story = {
+  name: 'with prefix / suffix / insetLabel, showClear, showArrow',
+};
+WithPrefixSuffixInsetLabelShowClearShowArrow.parameters = {
+  chromatic: { disableSnapshot: false },
+};
 
-    cityChange(city) {
-        this.setState({
-            city,
-        });
-    }
+export const WithDefaultSelected = () => (
+  <Select
+    style={{
+      width: '250px',
+    }}
+    defaultValue={1}
+  >
+    <Option value={1}>opt1</Option>
+    <Option value={2}>opt2</Option>
+    <Option value={3}>opt3</Option>
+    <Option value="4">opt4</Option>
+  </Select>
+);
+
+WithDefaultSelected.story = {
+  name: 'with default selected',
+};
 
-    render() {
-        const { provinces, citys, city } = this.state;
-        return (
-            <React.Fragment>
-                <Select
-                    style={{
-                        width: '150px',
-                        margin: '10px',
-                    }}
-                    onChange={this.provinceChange}
-                    defaultValue={provinces[0]}
-                >
-                    {provinces.map(pro => (
-                        <Option value={pro} key={pro}>
-                            {pro}
-                        </Option>
-                    ))}
-                </Select>
-                <Select
-                    style={{
-                        width: '150px',
-                        margin: '10px',
-                    }}
-                    value={city}
-                    onChange={this.cityChange}
-                >
-                    {citys.map(c => (
-                        <Option value={c} key={c}>
-                            {c}
-                        </Option>
-                    ))}
-                </Select>
-            </React.Fragment>
-        );
-    }
-}
+export const WithScrollbar = () => (
+  <Select
+    style={{
+      width: '250px',
+    }}
+    defaultValue={1}
+  >
+    <Option value={1}>opt1</Option>
+    <Option value={2}>opt2</Option>
+    <Option value={3}>opt3</Option>
+    <Option value="4">opt4</Option>
+    <Option value={5}>opt5</Option>
+    <Option value={6}>opt6</Option>
+    <Option value={7}>opt7</Option>
+    <Option value="8">opt8</Option>
+    <Option value={9}>opt9</Option>
+    <Option value={10}>opt10dfsdfsdfdsfdsfsdf</Option>
+    <Option value={11}>opt11</Option>
+    <Option value="12">opt12jfldsjflsdjlfldjslfjhifsdfdsfdsffdsodsjlfhjl</Option>
+  </Select>
+);
+
+WithScrollbar.story = {
+  name: 'with scrollbar',
+};
 
-stories.add('select 联动', () => <Link />);
-stories.add('select multiple', () => (
-    <>
-        <Select
-            multiple={true}
-            max={10}
-            style={{
-                width: '180px',
-            }}
-            placeholder="fefe"
-        >
-            <Option value={1}>opt1</Option>
-            <Option value={2}>opt2</Option>
-            <Option value={3}>opt3</Option>
-            <Option value="4">opt4</Option>
-            <Option value={5}>opt5</Option>
-            <Option value={6}>opt6</Option>
-            <Option value={7}>opt7</Option>
-            <Option value={8}>opt8</Option>
-        </Select>
-        <br />
-        <br />
-        <Select
-            multiple={true}
-            style={{
-                width: '300px',
-            }}
-            defaultValue={[1, 2, 3]}
-            placeholder="fefe"
-        >
-            <Option value={1}>opt1</Option>
-            <Option value={2}>opt2</Option>
-            <Option value={3}>opt3</Option>
-            <Option value="4">opt4</Option>
-            <Option value={5}>opt5</Option>
-            <Option value={6}>opt6</Option>
-            <Option value={7}>opt7</Option>
-            <Option value={8}>opt8</Option>
-        </Select>
-        <br />
-        <br />
-        <Select
-            multiple={true}
-            style={{
-                width: '300px',
-            }}
-            defaultValue={[1, 2, 3]}
-            placeholder="fefe"
-            disabled
-            onSelect={(...res) => console.log(res)}
-            onDeselect={(...res) => console.log(res)}
-        >
-            <Option value={1}>opt1</Option>
-            <Option value={2}>opt2</Option>
-            <Option value={3}>opt3</Option>
-            <Option value="4">opt4</Option>
-            <Option value={5}>opt5</Option>
-            <Option value={6}>opt6</Option>
-            <Option value={7}>opt7</Option>
-            <Option value={8}>opt8</Option>
-        </Select>
-        <br />
-        <br />
-        maxTagCount = 3
+class Link extends React.Component {
+  get provinces() {
+    return ['Sichuan', 'Guangdong'];
+  }
+
+  get maps() {
+    return {
+      Sichuan: ['Chengdu', 'Dujiangyan'],
+      Guangdong: ['Guangzhou', 'Shenzhen', 'Dongguan'],
+    };
+  }
+
+  constructor() {
+    super();
+    this.state = {
+      provinces: this.provinces,
+      maps: this.maps,
+      citys: this.maps[this.provinces[0]],
+      city: this.maps[this.provinces[0]][0],
+    };
+    this.provinceChange = this.provinceChange.bind(this);
+    this.cityChange = this.cityChange.bind(this);
+  }
+
+  provinceChange(newProvince) {
+    const { maps } = this.state;
+    this.setState({
+      citys: maps[newProvince],
+      city: maps[newProvince][0],
+    });
+  }
+
+  cityChange(city) {
+    this.setState({
+      city,
+    });
+  }
+
+  render() {
+    const { provinces, citys, city } = this.state;
+    return (
+      <React.Fragment>
         <Select
-            multiple={true}
-            maxTagCount={3}
-            style={{
-                width: '350px',
-            }}
-            defaultValue={[1, 2, 3]}
-            placeholder="fefe"
-            insetLabel="标签"
-            onSelect={(...res) => console.log(res)}
-            onDeselect={(...res) => console.log(res)}
+          style={{
+            width: '150px',
+            margin: '10px',
+          }}
+          onChange={this.provinceChange}
+          defaultValue={provinces[0]}
         >
-            <Option value={1}>opt1</Option>
-            <Option value={2}>opt2</Option>
-            <Option value={3}>opt3</Option>
-            <Option value="4">opt4</Option>
-            <Option value={5}>opt5</Option>
-            <Option value={6}>opt6</Option>
-            <Option value={7}>opt7</Option>
-            <Option value={8}>opt8</Option>
+          {provinces.map(pro => (
+            <Option value={pro} key={pro}>
+              {pro}
+            </Option>
+          ))}
         </Select>
-        <br />
-        <br />
-        maxTagCount = 3, max=5
         <Select
-            multiple={true}
-            maxTagCount={3}
-            max={5}
-            style={{
-                width: '350px',
-            }}
-            defaultValue={[1, 2, 3]}
-            placeholder="fefe"
-            insetLabel="标签"
-            onSelect={(...res) => console.log(res)}
-            onDeselect={(...res) => console.log(res)}
+          style={{
+            width: '150px',
+            margin: '10px',
+          }}
+          value={city}
+          onChange={this.cityChange}
         >
-            <Option value={1}>opt1</Option>
-            <Option value={2}>opt2</Option>
-            <Option value={3}>opt3</Option>
-            <Option value="4">opt4</Option>
-            <Option value={5}>opt5</Option>
-            <Option value={6}>opt6</Option>
-            <Option value={7}>opt7</Option>
-            <Option value={8}>opt8</Option>
+          {citys.map(c => (
+            <Option value={c} key={c}>
+              {c}
+            </Option>
+          ))}
         </Select>
-    </>
-));
-stories.add('select disabled', () => (
+      </React.Fragment>
+    );
+  }
+}
+
+export const TwoSelectChangeAtTheSameTime = () => <Link />;
+
+TwoSelectChangeAtTheSameTime.story = {
+  name: 'two select change at the same time',
+};
+
+export const SelectMultiple = () => (
+  <>
     <Select
-        disabled
-        multiple={true}
-        max={10}
-        style={{
-            width: '250px',
-        }}
+      multiple={true}
+      max={10}
+      style={{
+        width: '180px',
+      }}
+      placeholder="fefe"
     >
-        <Option value={1}>opt1</Option>
-        <Option value={2} disabled>
-            opt2
-        </Option>
-        <Option value={3}>opt3</Option>
-        <Option value="4">opt4</Option>
+      <Option value={1}>opt1</Option>
+      <Option value={2}>opt2</Option>
+      <Option value={3}>opt3</Option>
+      <Option value="4">opt4</Option>
+      <Option value={5}>opt5</Option>
+      <Option value={6}>opt6</Option>
+      <Option value={7}>opt7</Option>
+      <Option value={8}>opt8</Option>
+    </Select>
+    <br />
+    <br />
+    <Select
+      multiple={true}
+      style={{
+        width: '300px',
+      }}
+      defaultValue={[1, 2, 3]}
+      placeholder="fefe"
+    >
+      <Option value={1}>opt1</Option>
+      <Option value={2}>opt2</Option>
+      <Option value={3}>opt3</Option>
+      <Option value="4">opt4</Option>
+      <Option value={5}>opt5</Option>
+      <Option value={6}>opt6</Option>
+      <Option value={7}>opt7</Option>
+      <Option value={8}>opt8</Option>
     </Select>
-));
+    <br />
+    <br />
+    <Select
+      multiple={true}
+      style={{
+        width: '300px',
+      }}
+      defaultValue={[1, 2, 3]}
+      placeholder="fefe"
+      disabled
+      onSelect={(...res) => console.log(res)}
+      onDeselect={(...res) => console.log(res)}
+    >
+      <Option value={1}>opt1</Option>
+      <Option value={2}>opt2</Option>
+      <Option value={3}>opt3</Option>
+      <Option value="4">opt4</Option>
+      <Option value={5}>opt5</Option>
+      <Option value={6}>opt6</Option>
+      <Option value={7}>opt7</Option>
+      <Option value={8}>opt8</Option>
+    </Select>
+    <br />
+    <br />
+    maxTagCount = 3
+    <Select
+      multiple={true}
+      maxTagCount={3}
+      style={{
+        width: '350px',
+      }}
+      defaultValue={[1, 2, 3]}
+      placeholder="fefe"
+      insetLabel="标签"
+      onSelect={(...res) => console.log(res)}
+      onDeselect={(...res) => console.log(res)}
+    >
+      <Option value={1}>opt1</Option>
+      <Option value={2}>opt2</Option>
+      <Option value={3}>opt3</Option>
+      <Option value="4">opt4</Option>
+      <Option value={5}>opt5</Option>
+      <Option value={6}>opt6</Option>
+      <Option value={7}>opt7</Option>
+      <Option value={8}>opt8</Option>
+    </Select>
+    <br />
+    <br />
+    maxTagCount = 3, max=5
+    <Select
+      multiple={true}
+      maxTagCount={3}
+      max={5}
+      style={{
+        width: '350px',
+      }}
+      defaultValue={[1, 2, 3]}
+      placeholder="fefe"
+      insetLabel="标签"
+      onSelect={(...res) => console.log(res)}
+      onDeselect={(...res) => console.log(res)}
+    >
+      <Option value={1}>opt1</Option>
+      <Option value={2}>opt2</Option>
+      <Option value={3}>opt3</Option>
+      <Option value="4">opt4</Option>
+      <Option value={5}>opt5</Option>
+      <Option value={6}>opt6</Option>
+      <Option value={7}>opt7</Option>
+      <Option value={8}>opt8</Option>
+    </Select>
+  </>
+);
+
+SelectMultiple.story = {
+  name: 'select multiple',
+};
+SelectMultiple.parameters =  {
+  chromatic: { disableSnapshot: false },
+};
+
+export const SelectDisabled = () => (
+  <Select
+    disabled
+    multiple={true}
+    max={10}
+    style={{
+      width: '250px',
+    }}
+  >
+    <Option value={1}>opt1</Option>
+    <Option value={2} disabled>
+      opt2
+    </Option>
+    <Option value={3}>opt3</Option>
+    <Option value="4">opt4</Option>
+  </Select>
+);
+
+SelectDisabled.story = {
+  name: 'select disabled',
+};
 
 function filter(input, option) {
-    console.log(option);
-    return option.label.includes(input);
+  console.log(option);
+  return option.label.includes(input);
 }
 
 const spanStyle = {
-    display: 'inline-block',
-    marginRight: '8px',
-    width: '16px',
-    height: '16px',
-    borderRadius: '50%',
-    border: '1px solid var(--semi-color-bg-1)',
+  display: 'inline-block',
+  marginRight: '8px',
+  width: '16px',
+  height: '16px',
+  borderRadius: '50%',
+  border: '1px solid var(--semi-color-bg-1)',
 };
 const colorOptions = [
-    {
-        value: 'grey-1',
-        spanStyle: { ...spanStyle, backgroundColor: 'rgb(107, 116, 117)' },
-    },
-    {
-        value: 'purple-5',
-        spanStyle: { ...spanStyle, backgroundColor: 'rgb(158, 40, 179)' },
-    },
-    {
-        value: 'pink-2',
-        spanStyle: { ...spanStyle, backgroundColor: 'rgb(233, 30, 99)' },
-    },
-    {
-        value: 'blue-3',
-        spanStyle: { ...spanStyle, backgroundColor: 'rgb(0, 119, 250)' },
-    },
+  {
+    value: 'grey-1',
+    spanStyle: { ...spanStyle, backgroundColor: 'rgb(107, 116, 117)' },
+  },
+  {
+    value: 'purple-5',
+    spanStyle: { ...spanStyle, backgroundColor: 'rgb(158, 40, 179)' },
+  },
+  {
+    value: 'pink-2',
+    spanStyle: { ...spanStyle, backgroundColor: 'rgb(233, 30, 99)' },
+  },
+  {
+    value: 'blue-3',
+    spanStyle: { ...spanStyle, backgroundColor: 'rgb(0, 119, 250)' },
+  },
 ];
 const alignStyle = {
-    display: 'flex',
-    alignItems: 'center',
+  display: 'flex',
+  alignItems: 'center',
 };
 
 const customFilter = (input, option) => {
-    return option.value.includes(input);
+  return option.value.includes(input);
 };
 
-stories.add('select filter single', () => (
-    <div>
-        <h5>默认筛选</h5>
-        <Select
-            filter
+export const SelectFilterSingle = () => (
+  <div>
+    <h5>默认筛选</h5>
+    <Select
+      filter
+      style={{
+        width: '250px',
+        margin: 10,
+      }}
+      autoFocus
+      onFocus={() => console.log('onFocus')}
+      onBlur={() => console.log('onBlur')}
+    >
+      <Option value={1}>opt1</Option>
+      <Option value={2} disabled>
+        disabled
+      </Option>
+      <Option value={3}>Lucy</Option>
+      <Option value="4">bay</Option>
+      <Option value="5">sert</Option>
+      <Option value="6">wym</Option>
+      <Option value="7" disabled>
+        meno
+      </Option>
+      <Option value="8">opts</Option>
+    </Select>
+    <h5>自定义筛选函数</h5>
+    <Select
+      style={{
+        width: '250px',
+        margin: 10,
+      }}
+      filter={filter}
+      onBlur={() => console.log('onBlur')}
+      onFocus={() => console.log('onFocus')}
+    >
+      <Option value={1}>opt1(value:1)</Option>
+      <Option value={2}>mike(value:2)</Option>
+      <Option value={3}>Lucy(value:3)</Option>
+      <Option value={4}>bay(value:4)</Option>
+    </Select>
+    <h5>filter为true,但option label为node时</h5>
+    <Select
+      style={{
+        width: '250px',
+        margin: 10,
+      }}
+      filter={customFilter}
+      onChange={v => console.log(v)}
+      insetLabel="insetLabel"
+      onFocus={() => console.log('onFocus')}
+      onBlur={() => console.log('onBlur')}
+    >
+      {colorOptions.map(option => (
+        <Option value={option.value} key={option.value}>
+          <div style={alignStyle}>
+            <span style={option.spanStyle}></span>
+            {option.value}
+          </div>
+        </Option>
+      ))}
+    </Select>
+  </div>
+);
+
+SelectFilterSingle.story = {
+  name: 'select filter single',
+};
+
+export const SelectFilterMultiple = () => (
+  <>
+    <Select
+      filter
+      multiple={true}
+      style={{
+        width: '250px',
+      }}
+      placeholder="fefe"
+    >
+      <Option value={1}>opt1</Option>
+      <Option value={2}>opt2</Option>
+      <Option value={3}>opt22</Option>
+      <Option value={3}>opt3</Option>
+      <Option value={4}>opt4</Option>
+      <Option value={5}>opt5</Option>
+      <Option value={6}>opt6</Option>
+      <Option value={7}>opt7</Option>
+      <Option value={8}>opt8</Option>
+    </Select>
+    <Select
+      filter
+      multiple={true}
+      maxTagCount={3}
+      style={{
+        width: '270px',
+      }}
+      placeholder="fefe"
+    >
+      <Option value={1}>opt1</Option>
+      <Option value={2}>opt2</Option>
+      <Option value={3}>opt22</Option>
+      <Option value={3}>opt3</Option>
+      <Option value={4}>opt4</Option>
+      <Option value={5}>opt5</Option>
+      <Option value={6}>opt6</Option>
+      <Option value={7}>opt7</Option>
+      <Option value={8}>opt8</Option>
+    </Select>
+  </>
+);
+
+SelectFilterMultiple.story = {
+  name: 'select filter multiple',
+};
+
+const OptionLabelProp = () => {
+  const [value, setValue] = useState(1);
+  return (
+    <>
+      设置optionLabelProp属性(默认为'children')为'value'时,回填到选择框中的文本会是Option.value
+      <br></br>
+      <Select
+        style={{
+          width: '250px',
+        }}
+        defaultValue={1}
+        optionLabelProp="value"
+      >
+        <Option value={1}>opt1</Option>
+        <Option value={2}>opt2</Option>
+        <Option value={3}>
+          <span
             style={{
-                width: '250px',
-                margin: 10,
+              color: 'pink',
             }}
-            autoFocus
-            onFocus={() => console.log('onFocus')}
-            onBlur={() => console.log('onBlur')}
-        >
-            <Option value={1}>opt1</Option>
-            <Option value={2} disabled>
-                disabled
-            </Option>
-            <Option value={3}>Lucy</Option>
-            <Option value="4">bay</Option>
-            <Option value="5">sert</Option>
-            <Option value="6">wym</Option>
-            <Option value="7" disabled>
-                meno
-            </Option>
-            <Option value="8">opts</Option>
-        </Select>
-        <h5>自定义筛选函数</h5>
-        <Select
+          >
+            opt3 Node
+          </span>
+        </Option>
+        <Option value="4">
+          <span
+            style={{
+              color: 'red',
+            }}
+          >
+            testNode
+          </span>
+        </Option>
+      </Select>
+      <br />
+      <br />
+      <Select
+        style={{
+          width: '250px',
+        }}
+        value={value}
+        optionLabelProp="value"
+        onChange={setValue}
+      >
+        <Option value={1}>opt1</Option>
+        <Option value={2}>opt2</Option>
+        <Option value={3}>
+          <span
+            style={{
+              color: 'pink',
+            }}
+          >
+            opt3 Node
+          </span>
+        </Option>
+        <Option value="4">
+          <span
             style={{
-                width: '250px',
-                margin: 10,
+              color: 'red',
             }}
-            filter={filter}
-            onBlur={() => console.log('onBlur')}
-            onFocus={() => console.log('onFocus')}
+          >
+            testNode
+          </span>
+        </Option>
+      </Select>
+      <br />
+      <br />
+      <Select
+        style={{
+          width: '250px',
+        }}
+        defaultValue={1}
+      >
+        <Option value={1}>children Label Text 1</Option>
+        <Option value={2}>opt2</Option>
+        <Option value={3}>opt3</Option>
+        <Option value="4">
+          <span
+            style={{
+              color: 'red',
+            }}
+          >
+            testNode
+          </span>
+        </Option>
+      </Select>
+      <Select
+        style={{
+          width: '250px',
+        }}
+        defaultValue={1}
+        filter
+        optionLabelProp="value"
+      >
+        <Option value={1}>children Label Text 1</Option>
+        <Option value={2}>opt2</Option>
+        <Option value={3}>opt3</Option>
+        <Option value="4">
+          <span
+            style={{
+              color: 'red',
+            }}
+          >
+            testNode
+          </span>
+        </Option>
+      </Select>
+      <br />
+      <br />
+      多选
+      <Select
+        style={{
+          width: '250px',
+        }}
+        multiple
+        filter
+        optionLabelProp="value"
+      >
+        <Option value={1}>children Label Text 1</Option>
+        <Option value={2}>opt2</Option>
+        <Option value={3}>opt3</Option>
+        <Option value="4">
+          <span
+            style={{
+              color: 'red',
+            }}
+          >
+            testNode
+          </span>
+        </Option>
+      </Select>
+    </>
+  );
+};
+
+class CustomRender extends React.Component {
+  constructor() {
+    super();
+    this.state = {
+      list: [
+        {
+          name: '夏可漫',
+          email: '[email protected]',
+          abbr: 'XK',
+          color: 'amber',
+        },
+        {
+          name: '申悦',
+          email: '[email protected]',
+          abbr: 'SY',
+          color: 'indigo',
+        },
+        {
+          name: '曲晨一',
+          email: '[email protected]',
+          abbr: 'CY',
+          color: 'blue',
+        },
+        {
+          name: '文嘉茂',
+          email: '[email protected]',
+          abbr: 'JM',
+          color: 'cyan',
+        },
+      ],
+    };
+  }
+
+  renderCustomOption(item) {
+    let optionStyle = {
+      display: 'flex',
+    };
+    return (
+      <Option value={item.name} style={optionStyle} showTick={false} {...item}>
+        <Avatar color={item.color} size="small">
+          {item.abbr}
+        </Avatar>
+        <div
+          style={{
+            marginLeft: 4,
+          }}
         >
-            <Option value={1}>opt1(value:1)</Option>
-            <Option value={2}>mike(value:2)</Option>
-            <Option value={3}>Lucy(value:3)</Option>
-            <Option value={4}>bay(value:4)</Option>
-        </Select>
-        <h5>filter为true,但option label为node时</h5>
-        <Select
+          <p
+            style={{
+              fontSize: 14,
+              margin: 4,
+            }}
+          >
+            {item.name}
+          </p>
+          <p
             style={{
-                width: '250px',
-                margin: 10,
+              margin: 4,
             }}
-            filter={customFilter}
-            onChange={v => console.log(v)}
-            insetLabel="insetLabel"
-            onFocus={() => console.log('onFocus')}
-            onBlur={() => console.log('onBlur')}
+          >
+            {item.email}
+          </p>
+        </div>
+      </Option>
+    );
+  }
+
+  renderSelectedItem(optionNode) {
+    return (
+      <div>
+        <Avatar color={optionNode.color} size="small">
+          {optionNode.abbr}
+        </Avatar>
+        <span
+          style={{
+            margin: 8,
+          }}
         >
-            {colorOptions.map(option => (
-                <Option value={option.value} key={option.value}>
-                    <div style={alignStyle}>
-                        <span style={option.spanStyle}></span>
-                        {option.value}
-                    </div>
-                </Option>
-            ))}
+          {optionNode.email}
+        </span>
+      </div>
+    );
+  }
+
+  renderMultipleSelectedItem(optionNode) {
+    let content = (
+      <div>
+        <Avatar color={optionNode.color} size="small">
+          {optionNode.abbr}
+        </Avatar>
+      </div>
+    );
+    return {
+      isRenderInTag: true,
+      content,
+    };
+  }
+
+  renderMultipleWithoutTag(optionNode, { onClose, index }) {
+    let content = (
+      <div>
+        <Avatar color={optionNode.color} size="small">
+          {optionNode.abbr}
+        </Avatar>
+      </div>
+    );
+    return {
+      isRenderInTag: false,
+      content,
+    };
+  }
+
+  render() {
+    const { list } = this.state;
+    return (
+      <React.Fragment>
+        <Select
+          style={{
+            width: 300,
+            height: 40,
+          }}
+          onChange={this.provinceChange}
+          defaultValue={'夏可漫'}
+          renderSelectedItem={this.renderSelectedItem}
+        >
+          {list.map(item => this.renderCustomOption(item))}
         </Select>
-    </div>
-));
-stories.add('select filter multiple', () => (
-    <>
         <Select
-            filter
-            multiple={true}
-            style={{
-                width: '250px',
-            }}
-            placeholder="fefe"
+          style={{
+            width: 360,
+            height: 60,
+            marginTop: 20,
+          }}
+          onChange={this.provinceChange}
+          defaultValue={['夏可漫', '申悦']}
+          multiple
+          renderSelectedItem={this.renderMultipleSelectedItem}
         >
-            <Option value={1}>opt1</Option>
-            <Option value={2}>opt2</Option>
-            <Option value={3}>opt22</Option>
-            <Option value={3}>opt3</Option>
-            <Option value={4}>opt4</Option>
-            <Option value={5}>opt5</Option>
-            <Option value={6}>opt6</Option>
-            <Option value={7}>opt7</Option>
-            <Option value={8}>opt8</Option>
+          {list.map(item => this.renderCustomOption(item))}
         </Select>
         <Select
-            filter
-            multiple={true}
-            maxTagCount={3}
-            style={{
-                width: '270px',
-            }}
-            placeholder="fefe"
+          style={{
+            width: 360,
+            height: 60,
+            marginTop: 20,
+          }}
+          onChange={this.provinceChange}
+          defaultValue={['夏可漫', '申悦']}
+          multiple
+          renderSelectedItem={this.renderMultipleWithoutTag}
         >
-            <Option value={1}>opt1</Option>
-            <Option value={2}>opt2</Option>
-            <Option value={3}>opt22</Option>
-            <Option value={3}>opt3</Option>
-            <Option value={4}>opt4</Option>
-            <Option value={5}>opt5</Option>
-            <Option value={6}>opt6</Option>
-            <Option value={7}>opt7</Option>
-            <Option value={8}>opt8</Option>
+          {list.map(item => this.renderCustomOption(item))}
         </Select>
-    </>
-));
-
-const OptionLabelProp = () => {
-    const [value, setValue] = useState(1);
-    return (
-        <>
-            设置optionLabelProp属性(默认为'children')为'value'时,回填到选择框中的文本会是Option.value
-            <br></br>
-            <Select
-                style={{
-                    width: '250px',
-                }}
-                defaultValue={1}
-                optionLabelProp="value"
-            >
-                <Option value={1}>opt1</Option>
-                <Option value={2}>opt2</Option>
-                <Option value={3}>
-                    <span
-                        style={{
-                            color: 'pink',
-                        }}
-                    >
-                        opt3 Node
-                    </span>
-                </Option>
-                <Option value="4">
-                    <span
-                        style={{
-                            color: 'red',
-                        }}
-                    >
-                        testNode
-                    </span>
-                </Option>
-            </Select>
-            <br />
-            <br />
-            <Select
-                style={{
-                    width: '250px',
-                }}
-                value={value}
-                optionLabelProp="value"
-                onChange={setValue}
-            >
-                <Option value={1}>opt1</Option>
-                <Option value={2}>opt2</Option>
-                <Option value={3}>
-                    <span
-                        style={{
-                            color: 'pink',
-                        }}
-                    >
-                        opt3 Node
-                    </span>
-                </Option>
-                <Option value="4">
-                    <span
-                        style={{
-                            color: 'red',
-                        }}
-                    >
-                        testNode
-                    </span>
-                </Option>
-            </Select>
-            <br />
-            <br />
-            <Select
-                style={{
-                    width: '250px',
-                }}
-                defaultValue={1}
-            >
-                <Option value={1}>children Label Text 1</Option>
-                <Option value={2}>opt2</Option>
-                <Option value={3}>opt3</Option>
-                <Option value="4">
-                    <span
-                        style={{
-                            color: 'red',
-                        }}
-                    >
-                        testNode
-                    </span>
-                </Option>
-            </Select>
-            <Select
-                style={{
-                    width: '250px',
-                }}
-                defaultValue={1}
-                filter
-                optionLabelProp="value"
-            >
-                <Option value={1}>children Label Text 1</Option>
-                <Option value={2}>opt2</Option>
-                <Option value={3}>opt3</Option>
-                <Option value="4">
-                    <span
-                        style={{
-                            color: 'red',
-                        }}
-                    >
-                        testNode
-                    </span>
-                </Option>
-            </Select>
-            <br />
-            <br />
-            多选
-            <Select
-                style={{
-                    width: '250px',
-                }}
-                multiple
-                filter
-                optionLabelProp="value"
-            >
-                <Option value={1}>children Label Text 1</Option>
-                <Option value={2}>opt2</Option>
-                <Option value={3}>opt3</Option>
-                <Option value="4">
-                    <span
-                        style={{
-                            color: 'red',
-                        }}
-                    >
-                        testNode
-                    </span>
-                </Option>
-            </Select>
-        </>
+      </React.Fragment>
     );
-};
+  }
+}
 
-class CustomRender extends React.Component {
-    constructor() {
-        super();
-        this.state = {
-            list: [
-                {
-                    name: '夏可漫',
-                    email: '[email protected]',
-                    abbr: 'XK',
-                    color: 'amber',
-                },
-                {
-                    name: '申悦',
-                    email: '[email protected]',
-                    abbr: 'SY',
-                    color: 'indigo',
-                },
-                {
-                    name: '曲晨一',
-                    email: '[email protected]',
-                    abbr: 'CY',
-                    color: 'blue',
-                },
-                {
-                    name: '文嘉茂',
-                    email: '[email protected]',
-                    abbr: 'JM',
-                    color: 'cyan',
-                },
-            ],
-        };
-    }
+export const RenderSelectedItem = () => (
+  <>
+    renderSelectedItem
+    <CustomRender />
+    <br />
+    <br />
+    OptionLabelProp
+    <OptionLabelProp />
+  </>
+);
+
+RenderSelectedItem.story = {
+  name: 'renderSelectedItem',
+};
 
-    renderCustomOption(item) {
-        let optionStyle = {
-            display: 'flex',
-        };
-        return (
-            <Option value={item.name} style={optionStyle} showTick={false} {...item}>
-                <Avatar color={item.color} size="small">
-                    {item.abbr}
-                </Avatar>
-                <div
-                    style={{
-                        marginLeft: 4,
-                    }}
-                >
-                    <p
-                        style={{
-                            fontSize: 14,
-                            margin: 4,
-                        }}
-                    >
-                        {item.name}
-                    </p>
-                    <p
-                        style={{
-                            margin: 4,
-                        }}
-                    >
-                        {item.email}
-                    </p>
-                </div>
-            </Option>
-        );
-    }
+RenderSelectedItem.parameters =  {
+  chromatic: { disableSnapshot: false },
+};
 
-    renderSelectedItem(optionNode) {
-        return (
-            <div>
-                <Avatar color={optionNode.color} size="small">
-                    {optionNode.abbr}
-                </Avatar>
-                <span
-                    style={{
-                        margin: 8,
-                    }}
-                >
-                    {optionNode.email}
-                </span>
+const ControledSelect = () => {
+  const [value, setValue] = useState('nick');
+  const [value2, setValue2] = useState('jerry');
+  const [value3, setValue3] = useState();
+  const [value4, setValue4] = useState(['nick']);
+  const [value5, setValue5] = useState();
+  return (
+    <>
+      <span>value + onChange</span>
+      <Select
+        value={value}
+        onChange={setValue}
+        style={{
+          width: 200,
+        }}
+      >
+        <Option value="nick">nick</Option>
+        <Option value="jerry">jerry</Option>
+        <Option value="mark">mark</Option>
+      </Select>
+
+      <br />
+      <br />
+      <span>只传value,不传onChange</span>
+      <Select
+        value={value2}
+        style={{
+          width: 200,
+        }}
+      >
+        <Option value="nick">nick</Option>
+        <Option value="jerry">jerry</Option>
+        <Option value="mark">mark</Option>
+      </Select>
+      <br />
+      <br />
+
+      <span>value + onChange , 多选</span>
+      <Select
+        value={value3}
+        onChange={setValue3}
+        multiple
+        style={{
+          width: 200,
+        }}
+      >
+        <Option value="nick">nick</Option>
+        <Option value="jerry">jerry</Option>
+        <Option value="mark">mark</Option>
+        <Option value="nick2">nick2</Option>
+        <Option value="jerry2">jerry2</Option>
+        <Option value="mark2">mark2</Option>
+      </Select>
+      <br />
+      <br />
+
+      <span>value, 多选</span>
+      <Select
+        value={value4}
+        multiple
+        style={{
+          width: 200,
+        }}
+      >
+        <Option value="nick">nick</Option>
+        <Option value="jerry">jerry</Option>
+        <Option value="mark">mark</Option>
+      </Select>
+
+      <br />
+      <h5>filter为true,但option label为node时</h5>
+      <Select
+        style={{
+          width: '250px',
+        }}
+        filter={customFilter}
+        onChange={v => console.log(v)}
+        insetLabel="insetLabel"
+        value={value5}
+        onChange={setValue5}
+      >
+        {colorOptions.map(option => (
+          <Option value={option.value} key={option.value}>
+            <div style={alignStyle}>
+              <span style={option.spanStyle}></span>
+              {option.value}
             </div>
-        );
-    }
+          </Option>
+        ))}
+      </Select>
+    </>
+  );
+};
 
-    renderMultipleSelectedItem(optionNode) {
-        let content = (
-            <div>
-                <Avatar color={optionNode.color} size="small">
-                    {optionNode.abbr}
-                </Avatar>
-            </div>
-        );
-        return {
-            isRenderInTag: true,
-            content,
-        };
-    }
+export const Controlled = () => <ControledSelect></ControledSelect>;
 
-    renderMultipleWithoutTag(optionNode, { onClose, index }) {
-        let content = (
-            <div>
-                <Avatar color={optionNode.color} size="small">
-                    {optionNode.abbr}
-                </Avatar>
-            </div>
-        );
-        return {
-            isRenderInTag: false,
-            content,
-        };
-    }
+Controlled.story = {
+  name: 'controlled',
+};
 
-    render() {
-        const { list } = this.state;
-        return (
-            <React.Fragment>
-                <Select
-                    style={{
-                        width: 300,
-                        height: 40,
-                    }}
-                    onChange={this.provinceChange}
-                    defaultValue={'夏可漫'}
-                    renderSelectedItem={this.renderSelectedItem}
-                >
-                    {list.map(item => this.renderCustomOption(item))}
-                </Select>
-                <Select
-                    style={{
-                        width: 360,
-                        height: 60,
-                        marginTop: 20,
-                    }}
-                    onChange={this.provinceChange}
-                    defaultValue={['夏可漫', '申悦']}
-                    multiple
-                    renderSelectedItem={this.renderMultipleSelectedItem}
-                >
-                    {list.map(item => this.renderCustomOption(item))}
-                </Select>
-                <Select
-                    style={{
-                        width: 360,
-                        height: 60,
-                        marginTop: 20,
-                    }}
-                    onChange={this.provinceChange}
-                    defaultValue={['夏可漫', '申悦']}
-                    multiple
-                    renderSelectedItem={this.renderMultipleWithoutTag}
-                >
-                    {list.map(item => this.renderCustomOption(item))}
-                </Select>
-            </React.Fragment>
-        );
-    }
-}
+const UnControledSelect = () => {
+  const onChange = value => {
+    console.log(value);
+  };
 
-stories.add('自定义已选标签渲染', () => (
+  return (
     <>
-        renderSelectedItem
-        <CustomRender />
-        <br />
-        <br />
-        OptionLabelProp
-        <OptionLabelProp />
+      <h5>defaultValue在list中不存在</h5>
+      <Select
+        defaultValue={90}
+        onChange={onChange}
+        style={{
+          width: 200,
+        }}
+      >
+        <Option value={20}>nick</Option>
+        <Option value={10}>jerry</Option>
+        <Option value={5}>mark</Option>
+      </Select>
+      <h5>defaultValue在list中存在</h5>
+      <Select
+        defaultValue={10}
+        onChange={onChange}
+        style={{
+          width: 200,
+        }}
+      >
+        <Option value={20}>nick</Option>
+        <Option value={10}>jerry</Option>
+        <Option value={5}>mark</Option>
+      </Select>
     </>
-));
+  );
+};
+
+export { UnControledSelect };
+UnControledSelect.story = {
+  name: '非受控组件'
+};
+
+export const TestScroll = () => (
+  <div
+    style={{
+      marginTop: '600px',
+      marginBottom: '50px',
+    }}
+  >
+    <Select
+      style={{
+        width: '150px',
+      }}
+    >
+      <Option value="tony">IronMan</Option>
+      <Option value="Thor" disabled>
+        Thor
+      </Option>
+      <Option value="steve">Caption</Option>
+      <Option value="peter">SpiderBoy</Option>
+    </Select>
+  </div>
+);
+
+TestScroll.story = {
+  name: 'test scroll',
+};
+
+let optionList = [
+  {
+    value: 'tony',
+    label: 'Ironman',
+  },
+  {
+    value: 'Thor',
+    label: 'Thor',
+  },
+  {
+    value: 'steve',
+    label: 'Caption',
+  },
+  {
+    value: 'peter',
+    label: 'SpiderBoy',
+  },
+];
+
+export const OptionList = () => (
+  <Select
+    style={{
+      width: '100px',
+    }}
+    optionList={optionList}
+  ></Select>
+);
+
+OptionList.story = {
+  name: 'optionList',
+};
+
+export const InsetLabel = () => (
+  <>
+    <Select
+      style={{
+        width: 300,
+      }}
+      insetLabel="主播类型"
+      placeholder="请选择"
+      optionList={optionList}
+    ></Select>
+    <Select
+      style={{
+        width: 300,
+      }}
+      multiple
+      insetLabel="主播类型"
+      optionList={optionList}
+    ></Select>
+    <Select
+      style={{
+        width: 300,
+      }}
+      filter
+      insetLabel="主播类型"
+      optionList={optionList}
+    ></Select>
+    <Select
+      style={{
+        width: 300,
+      }}
+      filter
+      multiple
+      insetLabel="主播类型"
+      optionList={optionList}
+    ></Select>
+  </>
+);
 
-const ControledSelect = () => {
-    const [value, setValue] = useState('nick');
-    const [value2, setValue2] = useState('jerry');
-    const [value3, setValue3] = useState();
-    const [value4, setValue4] = useState(['nick']);
-    const [value5, setValue5] = useState();
-    return (
-        <>
-            <span>value + onChange</span>
-            <Select
-                value={value}
-                onChange={setValue}
-                style={{
-                    width: 200,
-                }}
-            >
-                <Option value="nick">nick</Option>
-                <Option value="jerry">jerry</Option>
-                <Option value="mark">mark</Option>
-            </Select>
-
-            <br />
-            <br />
-            <span>只传value,不传onChange</span>
-            <Select
-                value={value2}
-                style={{
-                    width: 200,
-                }}
-            >
-                <Option value="nick">nick</Option>
-                <Option value="jerry">jerry</Option>
-                <Option value="mark">mark</Option>
-            </Select>
-            <br />
-            <br />
-
-            <span>value + onChange , 多选</span>
-            <Select
-                value={value3}
-                onChange={setValue3}
-                multiple
-                style={{
-                    width: 200,
-                }}
-            >
-                <Option value="nick">nick</Option>
-                <Option value="jerry">jerry</Option>
-                <Option value="mark">mark</Option>
-                <Option value="nick2">nick2</Option>
-                <Option value="jerry2">jerry2</Option>
-                <Option value="mark2">mark2</Option>
-            </Select>
-            <br />
-            <br />
-
-            <span>value, 多选</span>
-            <Select
-                value={value4}
-                multiple
-                style={{
-                    width: 200,
-                }}
-            >
-                <Option value="nick">nick</Option>
-                <Option value="jerry">jerry</Option>
-                <Option value="mark">mark</Option>
-            </Select>
-
-            <br />
-            <h5>filter为true,但option label为node时</h5>
-            <Select
-                style={{
-                    width: '250px',
-                }}
-                filter={customFilter}
-                onChange={v => console.log(v)}
-                insetLabel="insetLabel"
-                value={value5}
-                onChange={setValue5}
-            >
-                {colorOptions.map(option => (
-                    <Option value={option.value} key={option.value}>
-                        <div style={alignStyle}>
-                            <span style={option.spanStyle}></span>
-                            {option.value}
-                        </div>
-                    </Option>
-                ))}
-            </Select>
-        </>
-    );
+InsetLabel.story = {
+  name: 'insetLabel',
 };
 
-stories.add('受控组件', () => <ControledSelect></ControledSelect>);
+export const ChangeOptionDynamic = () => {
+  function App() {
+    let [options, setOptions] = useState([]);
+    let [index, setIndex] = useState(0);
+
+    const addOption = () => {
+      const randomItem = optionList[index];
+      index = index + 1;
+      setIndex(index);
+      options = [...options, { ...randomItem }];
+      setOptions(options);
+    };
 
-const UnControledSelect = () => {
-    const onChange = value => {
-        console.log(value);
+    const reset = () => {
+      setOptions([]);
+      setIndex(0);
     };
 
     return (
-        <>
-            <h5>defaultValue在list中不存在</h5>
-            <Select
-                defaultValue={90}
-                onChange={onChange}
-                style={{
-                    width: 200,
-                }}
-            >
-                <Option value={20}>nick</Option>
-                <Option value={10}>jerry</Option>
-                <Option value={5}>mark</Option>
-            </Select>
-            <h5>defaultValue在list中存在</h5>
-            <Select
-                defaultValue={10}
-                onChange={onChange}
-                style={{
-                    width: 200,
-                }}
-            >
-                <Option value={20}>nick</Option>
-                <Option value={10}>jerry</Option>
-                <Option value={5}>mark</Option>
-            </Select>
-        </>
-    );
-};
-
-stories.add('非受控组件', () => <UnControledSelect></UnControledSelect>);
-stories.add('test scroll', () => (
-    <div
-        style={{
-            marginTop: '600px',
-            marginBottom: '50px',
-        }}
-    >
+      <div>
         <Select
-            style={{
-                width: '150px',
-            }}
+          style={{
+            width: '150px',
+          }}
+          defaultValue="tony"
         >
-            <Option value="tony">IronMan</Option>
-            <Option value="Thor" disabled>
-                Thor
-            </Option>
-            <Option value="steve">Caption</Option>
-            <Option value="peter">SpiderBoy</Option>
+          {options.map((option, idx) => (
+            <Select.Option key={option.key || idx} value={option.value}>
+              {option.label}
+            </Select.Option>
+          ))}
         </Select>
-    </div>
-));
-let optionList = [
-    {
-        value: 'tony',
-        label: 'Ironman',
-    },
-    {
-        value: 'Thor',
-        label: 'Thor',
-    },
-    {
-        value: 'steve',
-        label: 'Caption',
-    },
-    {
-        value: 'peter',
-        label: 'SpiderBoy',
-    },
-];
-stories.add('optionList方式传入', () => (
-    <Select
-        style={{
-            width: '100px',
-        }}
-        optionList={optionList}
-    ></Select>
-));
-stories.add('insetLabel', () => (
-    <>
-        <Select
-            style={{
-                width: 300,
-            }}
-            insetLabel="主播类型"
-            placeholder="请选择"
-            optionList={optionList}
-        ></Select>
-        <Select
-            style={{
-                width: 300,
-            }}
-            multiple
-            insetLabel="主播类型"
-            optionList={optionList}
-        ></Select>
-        <Select
-            style={{
-                width: 300,
-            }}
-            filter
-            insetLabel="主播类型"
-            optionList={optionList}
-        ></Select>
+        <h4>多选</h4>
         <Select
-            style={{
-                width: 300,
-            }}
-            filter
-            multiple
-            insetLabel="主播类型"
-            optionList={optionList}
-        ></Select>
-    </>
-));
-stories.add('change option dynamic', () => {
-    function App() {
-        let [options, setOptions] = useState([]);
-        let [index, setIndex] = useState(0);
-
-        const addOption = () => {
-            const randomItem = optionList[index];
-            index = index + 1;
-            setIndex(index);
-            options = [...options, { ...randomItem }];
-            setOptions(options);
-        };
+          style={{
+            width: '150px',
+          }}
+          multiple
+          defaultValue={['tony']}
+        >
+          {options.map((option, idx) => (
+            <Select.Option key={option.key || idx} value={option.value}>
+              {option.label}
+            </Select.Option>
+          ))}
+        </Select>
+        <button onClick={addOption}>add option</button>
+        <button onClick={reset}>reset</button>
+      </div>
+    );
+  }
 
-        const reset = () => {
-            setOptions([]);
-            setIndex(0);
-        };
+  return <App />;
+};
 
-        return (
-            <div>
-                <Select
-                    style={{
-                        width: '150px',
-                    }}
-                    defaultValue="tony"
-                >
-                    {options.map((option, idx) => (
-                        <Select.Option key={option.key || idx} value={option.value}>
-                            {option.label}
-                        </Select.Option>
-                    ))}
-                </Select>
-                <h4>多选</h4>
-                <Select
-                    style={{
-                        width: '150px',
-                    }}
-                    multiple
-                    defaultValue={['tony']}
-                >
-                    {options.map((option, idx) => (
-                        <Select.Option key={option.key || idx} value={option.value}>
-                            {option.label}
-                        </Select.Option>
-                    ))}
-                </Select>
-                <button onClick={addOption}>add option</button>
-                <button onClick={reset}>reset</button>
-            </div>
-        );
-    }
+ChangeOptionDynamic.story = {
+  name: 'change option dynamic',
+};
 
-    return <App />;
-});
 let list = [
-    {
-        value: 'tony',
-        label: 'Ironman',
-        otherKey: {
-            role: 1,
-        },
+  {
+    value: 'tony',
+    label: 'Ironman',
+    otherKey: {
+      role: 1,
     },
-    {
-        value: 'Thor',
-        label: 'Thor',
-        otherKey: {
-            role: 2,
-        },
+  },
+  {
+    value: 'Thor',
+    label: 'Thor',
+    otherKey: {
+      role: 2,
     },
-    {
-        value: 'steve',
-        label: 'Caption',
-        otherKey: {
-            role: 3,
-        },
+  },
+  {
+    value: 'steve',
+    label: 'Caption',
+    otherKey: {
+      role: 3,
     },
-    {
-        value: 'peter',
-        label: 'SpiderBoy',
-        otherKey: {
-            role: 4,
-        },
+  },
+  {
+    value: 'peter',
+    label: 'SpiderBoy',
+    otherKey: {
+      role: 4,
     },
+  },
 ];
 
 const SearchDemo1 = () => {
-    const [optionList, setOptionList] = useState(list);
-    const [loading, setLoading] = useState(false);
-
-    const handleSearch = value => {
-        setLoading(true);
-        let length = Math.ceil(Math.random() * 10);
-        let result = Array.from(
-            {
-                length,
-            },
-            (v, i) => {
-                return {
-                    value: value + i,
-                    label: value + i,
-                    otherKey: {
-                        role: i,
-                    },
-                };
-            }
-        );
-        setTimeout(() => {
-            setOptionList(result);
-            setLoading(false);
-        }, 1000);
-    };
-
-    const [value, setValue] = useState(optionList[0].value);
-
-    const onChange = value => {
-        console.log(value);
-        setValue(value);
-    };
-
-    return (
-        <div>
-            受控:
-            <Select
-                filter
-                style={{
-                    width: '150px',
-                }}
-                onSearch={v => handleSearch(v)}
-                optionList={optionList}
-                value={value}
-                loading={loading}
-                onChange={onChange}
-            ></Select>
-            非受控:
-            <Select
-                style={{
-                    width: '150px',
-                }}
-                filter
-                onSearch={v => handleSearch(v)}
-                optionList={optionList}
-                loading={loading}
-                onChange={onChange}
-            ></Select>
-            多选非受控
-            <Select
-                style={{
-                    width: '150px',
-                }}
-                filter
-                multiple
-                onSearch={v => handleSearch(v)}
-                optionList={optionList}
-                loading={loading}
-                onChange={onChange}
-            ></Select>
-        </div>
-    );
-};
-
-import debounce from 'lodash/debounce';
-
-class SearchDemo2 extends React.Component {
-    constructor() {
-        super();
-        this.state = {
-            loading: false,
-            optionList: [
-                {
-                    value: 'abc',
-                    label: '抖音',
-                    type: 1,
-                },
-                {
-                    value: 'hotsoon',
-                    label: '火山小视频',
-                    type: 2,
-                },
-                {
-                    value: 'pipixia',
-                    label: '皮皮虾',
-                    type: 3,
-                },
-                {
-                    value: 'toutiao',
-                    label: '今日头条',
-                    type: 4,
-                },
-            ],
-            value: [],
+  const [optionList, setOptionList] = useState(list);
+  const [loading, setLoading] = useState(false);
+
+  const handleSearch = value => {
+    setLoading(true);
+    let length = Math.ceil(Math.random() * 10);
+    let result = Array.from(
+      {
+        length,
+      },
+      (v, i) => {
+        return {
+          value: value + i,
+          label: value + i,
+          otherKey: {
+            role: i,
+          },
         };
-        this.handleSearch = debounce(this.handleSearch, 800).bind(this);
-        this.onChange = this.onChange.bind(this);
-        this.customRender = this.customRender.bind(this);
-    }
-
-    handleSearch(inputValue) {
-        this.setState({
-            loading: true,
-        });
-        let length = Math.ceil(Math.random() * 100);
-        let result = Array.from(
-            {
-                length,
-            },
-            (v, i) => {
-                return {
-                    value: inputValue + i,
-                    label: 'label' + i,
-                    type: i + 1,
-                };
-            }
-        );
-        setTimeout(() => {
-            this.setState({
-                optionList: result,
-                loading: false,
-            });
-        }, 2000);
-    }
-
-    onChange(value) {
-        this.setState({
-            value,
-        });
-        console.log(value);
-    }
-
-    customRender(optionNode) {
-        return optionNode.value + optionNode.label;
-    }
-
-    render() {
-        const { loading, optionList, value } = this.state;
-        return (
-            <div>
-                <Select
-                    style={{
-                        width: 150,
-                    }}
-                    filter
-                    labelInValue
-                    onSearch={this.handleSearch}
-                    optionList={optionList}
-                    loading={loading}
-                    onChange={this.onChange}
-                    placeholder="请选择"
-                ></Select>
-                <br />
-                <br />
-                <Select
-                    style={{
-                        width: 180,
-                    }}
-                    filter // labelInValue
-                    multiple
-                    value={value}
-                    renderSelectedItem={this.customRender}
-                    onSearch={this.handleSearch}
-                    optionList={optionList}
-                    loading={loading}
-                    onChange={this.onChange}
-                    placeholder="请选择"
-                ></Select>
-            </div>
-        );
-    }
-}
-
-stories.add('搜索', () => (
-    <>
-        <SearchDemo1 />
-        <SearchDemo2 />
-    </>
-));
-export const IncomeDetail = ({ config }) => {
-    const [detailList, setDetailList] = useState([]);
-    const [hasMore, setHasMore] = useState(true);
-    const [loading, setLoading] = useState();
-
-    const fetchData = (outParams = {}) => {
-        if (lock) {
-            return;
-        }
-
-        setLoading(true); // 参数
-        // 请求
-
-        fetch({
-            url: URL.user_profit,
-            method: 'get',
-            baseURL: config.webcast_host,
-            params,
-        })
-            .then(res => {
-                lock = false;
-                setLoading(false);
-                console.log('++++', data);
-            })
-            .catch(() => {
-                setLoading(false);
-                Toast.show('网络异常,请稍后重试');
-            });
-    };
+      }
+    );
+    setTimeout(() => {
+      setOptionList(result);
+      setLoading(false);
+    }, 1000);
+  };
 
-    useEffect(fetchData, []); // 监听滚动设置吸顶 以及加载更多
+  const [value, setValue] = useState(optionList[0].value);
 
-    useEffect(() => {
-        window.addEventListener('scroll', function() {
-            // 加载更多
-            const scrollY = window.scrollY;
-            const scrollHeight = document.documentElement.scrollHeight;
-            const screenHeight = screen.height;
+  const onChange = value => {
+    console.log(value);
+    setValue(value);
+  };
 
-            if (!loading && hasMore && scrollY + screenHeight + 300 > scrollHeight) {
-                fetchData();
-            }
-        });
-    }, [detailList.length]);
-    return (
-        <div>
-            <Select></Select>
-        </div>
-    );
-};
-stories.add('allowCreate', () => (
-    <Select
+  return (
+    <div>
+      受控:
+      <Select
+        filter
         style={{
-            width: 500,
+          width: '150px',
         }}
+        onSearch={v => handleSearch(v)}
         optionList={optionList}
-        allowCreate={true}
-        multiple={true}
-        filter={true}
-        onChange={v => console.log(v)}
-    ></Select>
-));
-stories.add('allowCreate custom render', () => (
-    <Select
+        value={value}
+        loading={loading}
+        onChange={onChange}
+      ></Select>
+      非受控:
+      <Select
         style={{
-            width: 500,
+          width: '150px',
         }}
+        filter
+        onSearch={v => handleSearch(v)}
         optionList={optionList}
-        allowCreate={true}
-        multiple={true}
-        filter={true}
-        onChange={v => console.log(v)}
-        renderCreateItem={v => `semi: ${v}`}
-    ></Select>
-));
+        loading={loading}
+        onChange={onChange}
+      ></Select>
+      多选非受控
+      <Select
+        style={{
+          width: '150px',
+        }}
+        filter
+        multiple
+        onSearch={v => handleSearch(v)}
+        optionList={optionList}
+        loading={loading}
+        onChange={onChange}
+      ></Select>
+    </div>
+  );
+};
 
-let AllowCreateControledDemo = () => {
-    let [value, setValue] = useState();
-    const optionList = [
+import debounce from 'lodash/debounce';
+
+class SearchDemo2 extends React.Component {
+  constructor() {
+    super();
+    this.state = {
+      loading: false,
+      optionList: [
         {
-            value: 'abc',
-            label: '抖音',
+          value: 'abc',
+          label: '抖音',
+          type: 1,
         },
         {
-            value: 'hotsoon',
-            label: '火山小视频',
+          value: 'hotsoon',
+          label: '火山小视频',
+          type: 2,
         },
         {
-            value: 'pipixia',
-            label: '皮皮虾',
+          value: 'pipixia',
+          label: '皮皮虾',
+          type: 3,
         },
         {
-            value: 'toutiao',
-            label: '今日头条',
+          value: 'toutiao',
+          label: '今日头条',
+          type: 4,
         },
-    ];
-    const [list, setList] = useState(optionList);
-
-    const handleSelect = v => {
-        var lastOne = v[v.length - 1];
-
-        if (lastOne && list.findIndex(item => item.value === lastOne) == -1) {
-            list.push({
-                value: lastOne,
-                label: lastOne,
-            });
-        }
-
-        setList(list);
-        setValue(v);
+      ],
+      value: [],
     };
+    this.handleSearch = debounce(this.handleSearch, 800).bind(this);
+    this.onChange = this.onChange.bind(this);
+    this.customRender = this.customRender.bind(this);
+  }
+
+  handleSearch(inputValue) {
+    this.setState({
+      loading: true,
+    });
+    let length = Math.ceil(Math.random() * 100);
+    let result = Array.from(
+      {
+        length,
+      },
+      (v, i) => {
+        return {
+          value: inputValue + i,
+          label: 'label' + i,
+          type: i + 1,
+        };
+      }
+    );
+    setTimeout(() => {
+      this.setState({
+        optionList: result,
+        loading: false,
+      });
+    }, 2000);
+  }
+
+  onChange(value) {
+    this.setState({
+      value,
+    });
+    console.log(value);
+  }
 
+  customRender(optionNode) {
+    return optionNode.value + optionNode.label;
+  }
+
+  render() {
+    const { loading, optionList, value } = this.state;
     return (
+      <div>
         <Select
-            style={{
-                width: 400,
-            }}
-            optionList={list}
-            allowCreate={true}
-            multiple={true}
-            filter={true}
-            value={value}
-            onChange={handleSelect}
+          style={{
+            width: 150,
+          }}
+          filter
+          labelInValue
+          onSearch={this.handleSearch}
+          optionList={optionList}
+          loading={loading}
+          onChange={this.onChange}
+          placeholder="请选择"
+        ></Select>
+        <br />
+        <br />
+        <Select
+          style={{
+            width: 180,
+          }}
+          filter // labelInValue
+          multiple
+          value={value}
+          renderSelectedItem={this.customRender}
+          onSearch={this.handleSearch}
+          optionList={optionList}
+          loading={loading}
+          onChange={this.onChange}
+          placeholder="请选择"
         ></Select>
+      </div>
     );
+  }
+}
+
+export const Search = () => (
+  <>
+    <SearchDemo1 />
+    <SearchDemo2 />
+  </>
+);
+
+Search.story = {
+  name: 'search',
 };
 
-const AllowCreateDemo = () => {
-    let [value, setValue] = useState();
-    const optionList = [
-        {
-            value: 'abc',
-            label: '抖音',
-        },
-        {
-            value: 'hotsoon',
-            label: '火山小视频',
-        },
-        {
-            value: 'pipixia',
-            label: '皮皮虾',
-        },
-        {
-            value: 'toutiao',
-            label: '今日头条',
-        },
-    ];
-    const [list, setList] = useState(optionList);
+export const IncomeDetail = ({ config = {}, params = {} }) => {
+  const [detailList, setDetailList] = useState([]);
+  const [hasMore, setHasMore] = useState(true);
+  const [loading, setLoading] = useState();
+  let lock;
 
-    const handleSelect = v => {
-        var lastOne = v[v.length - 1];
+  const fetchData = (outParams = {}) => {
+    if (lock) {
+      return;
+    }
 
-        if (lastOne && list.findIndex(item => item.value === lastOne) == -1) {
-            list.push({
-                value: lastOne,
-                label: lastOne,
-            });
-        }
+    setLoading(true); // 参数
+    // 请求
+
+    fetch({
+      url: URL.user_profit,
+      method: 'get',
+      baseURL: config.webcast_host,
+      params,
+    })
+      .then(res => {
+        lock = false;
+        setLoading(false);
+        console.log('++++', data);
+      })
+      .catch(() => {
+        setLoading(false);
+        Toast.show('网络异常,请稍后重试');
+      });
+  };
+
+  useEffect(fetchData, []); // 监听滚动设置吸顶 以及加载更多
+
+  useEffect(() => {
+    window.addEventListener('scroll', function() {
+      // 加载更多
+      const scrollY = window.scrollY;
+      const scrollHeight = document.documentElement.scrollHeight;
+      const screenHeight = screen.height;
+
+      if (!loading && hasMore && scrollY + screenHeight + 300 > scrollHeight) {
+        fetchData();
+      }
+    });
+  }, [detailList.length]);
+  return (
+    <div>
+      <Select></Select>
+    </div>
+  );
+};
 
-        setList(list); // setValue(v)
-    };
+export const AllowCreate = () => (
+  <Select
+    style={{
+      width: 500,
+    }}
+    optionList={optionList}
+    allowCreate={true}
+    multiple={true}
+    filter={true}
+    onChange={v => console.log(v)}
+  ></Select>
+);
+
+AllowCreate.story = {
+  name: 'allowCreate',
+};
 
-    return (
-        <Select
-            style={{
-                width: 400,
-            }}
-            optionList={list}
-            defaultValue={['abc', 'hotsoon']}
-            allowCreate={true}
-            multiple={true}
-            filter={true}
-            onChange={handleSelect}
-        ></Select>
-    );
+export const AllowCreateCustomRender = () => (
+  <Select
+    style={{
+      width: 500,
+    }}
+    optionList={optionList}
+    allowCreate={true}
+    multiple={true}
+    filter={true}
+    onChange={v => console.log(v)}
+    renderCreateItem={v => `semi: ${v}`}
+  ></Select>
+);
+
+AllowCreateCustomRender.story = {
+  name: 'allowCreate custom render',
 };
 
-stories.add('allowCreate 带默认值', () => <AllowCreateDemo />);
+let AllowCreateControledDemo = () => {
+  let [value, setValue] = useState();
+  const optionList = [
+    {
+      value: 'abc',
+      label: '抖音',
+    },
+    {
+      value: 'hotsoon',
+      label: '火山小视频',
+    },
+    {
+      value: 'pipixia',
+      label: '皮皮虾',
+    },
+    {
+      value: 'toutiao',
+      label: '今日头条',
+    },
+  ];
+  const [list, setList] = useState(optionList);
 
-class HideDemo extends React.Component {
-    constructor(props) {
-        super(props);
-        this.state = {
-            optionList: [
-                {
-                    value: 'abc',
-                    label: '抖音',
-                },
-                {
-                    value: 'hotsoon',
-                    label: '火山小视频',
-                },
-                {
-                    value: 'pipixia',
-                    label: '皮皮虾',
-                },
-                {
-                    value: 'toutiao',
-                    label: '今日头条',
-                },
-            ],
-            selectedItems: [],
-        };
-        this.onChange = this.onChange.bind(this);
-    }
+  const handleSelect = v => {
+    var lastOne = v[v.length - 1];
 
-    onChange(selectedItems) {
-        this.setState({
-            selectedItems,
-        });
+    if (lastOne && list.findIndex(item => item.value === lastOne) == -1) {
+      list.push({
+        value: lastOne,
+        label: lastOne,
+      });
     }
 
-    render() {
-        let { optionList, selectedItems } = this.state;
-        let filterOptions = optionList.filter(option => !selectedItems.includes(option.value));
-        return (
-            <Select
-                value={selectedItems}
-                multiple
-                style={{
-                    width: 300,
-                }}
-                onChange={this.onChange}
-                optionList={filterOptions}
-            ></Select>
-        );
-    }
-}
+    setList(list);
+    setValue(v);
+  };
 
-stories.add('自动隐藏已选项', () => <HideDemo></HideDemo>);
+  return (
+    <Select
+      style={{
+        width: 400,
+      }}
+      optionList={list}
+      allowCreate={true}
+      multiple={true}
+      filter={true}
+      value={value}
+      onChange={handleSelect}
+    ></Select>
+  );
+};
 
-class CustomCreate extends React.Component {
-    constructor(props) {
-        super(props);
-        this.state = {
-            optionList: [
-                {
-                    value: 'abc',
-                    label: '抖音',
-                },
-                {
-                    value: 'hotsoon',
-                    label: '火山小视频',
-                },
-                {
-                    value: 'pipixia',
-                    label: '皮皮虾',
-                },
-                {
-                    value: 'toutiao',
-                    label: '今日头条',
-                },
-                {
-                    value: 0,
-                    label: 0,
-                },
-            ],
-            selectedItems: ['fefe'],
-        };
-        this.onChange = this.onChange.bind(this);
-        this.customRender = this.customRender.bind(this);
-        this.search = this.search.bind(this);
-    }
+const AllowCreateDemo = () => {
+  let [value, setValue] = useState();
+  const optionList = [
+    {
+      value: 'abc',
+      label: '抖音',
+    },
+    {
+      value: 'hotsoon',
+      label: '火山小视频',
+    },
+    {
+      value: 'pipixia',
+      label: '皮皮虾',
+    },
+    {
+      value: 'toutiao',
+      label: '今日头条',
+    },
+  ];
+  const [list, setList] = useState(optionList);
 
-    onChange(selectedItems) {
-        console.log(selectedItems); // this.setState({ selectedItems, optionList: [] });
+  const handleSelect = v => {
+    var lastOne = v[v.length - 1];
 
-        this.setState({
-            selectedItems,
-        }); // this.setState({ optionList: [] });
+    if (lastOne && list.findIndex(item => item.value === lastOne) == -1) {
+      list.push({
+        value: lastOne,
+        label: lastOne,
+      });
     }
 
-    customRender(v) {
-        return (
-            <>
-                <span>label:{v.label}</span>
-                <span>value:{v.value}</span>
-            </>
-        );
-    }
+    setList(list); // setValue(v)
+  };
 
-    customCreate(inputValue, isFocus) {
-        let style = {
-            padding: 12,
-            cursor: 'pointer',
-            backgroundColor: isFocus ? 'var(--semi-color-fill-0)' : '#FFF',
-        };
-        return <div style={style}>{'create' + inputValue}</div>;
-    }
+  return (
+    <Select
+      style={{
+        width: 400,
+      }}
+      optionList={list}
+      defaultValue={['abc', 'hotsoon']}
+      allowCreate={true}
+      multiple={true}
+      filter={true}
+      onChange={handleSelect}
+    ></Select>
+  );
+};
 
-    search(inputValue) {
-        let length = Math.ceil(Math.random() * 10);
-        let result = Array.from(
-            {
-                length,
-            },
-            (v, i) => {
-                return {
-                    value: inputValue + i,
-                    label: inputValue + i,
-                    type: i + 1,
-                };
-            }
-        );
-        console.log(result); // result = result.concat(selectedOption);
-
-        this.setState({
-            optionList: result,
-        });
-    }
+export const AllowCreateWithDefaultValue = () => <AllowCreateDemo />;
 
-    render() {
-        let { optionList, selectedItems } = this.state;
-        return (
-            <>
-                <Select
-                    defaultValue={['abc']}
-                    filter
-                    style={{
-                        width: 300,
-                    }}
-                    multiple
-                    optionList={optionList}
-                    onSearch={this.search}
-                    onChange={this.onChange}
-                    emptyContent={null} // onChangeWithObject
-                ></Select>
-            </>
-        );
-    }
+AllowCreateWithDefaultValue.story = {
+  name: 'allowCreate with defaultValue',
+};
+
+class HideDemo extends React.Component {
+  constructor(props) {
+    super(props);
+    this.state = {
+      optionList: [
+        {
+          value: 'abc',
+          label: '抖音',
+        },
+        {
+          value: 'hotsoon',
+          label: '火山小视频',
+        },
+        {
+          value: 'pipixia',
+          label: '皮皮虾',
+        },
+        {
+          value: 'toutiao',
+          label: '今日头条',
+        },
+      ],
+      selectedItems: [],
+    };
+    this.onChange = this.onChange.bind(this);
+  }
+
+  onChange(selectedItems) {
+    this.setState({
+      selectedItems,
+    });
+  }
+
+  render() {
+    let { optionList, selectedItems } = this.state;
+    let filterOptions = optionList.filter(option => !selectedItems.includes(option.value));
+    return (
+      <Select
+        value={selectedItems}
+        multiple
+        style={{
+          width: 300,
+        }}
+        onChange={this.onChange}
+        optionList={filterOptions}
+      ></Select>
+    );
+  }
 }
 
-stories.add('CustomCreate', () => <CustomCreate></CustomCreate>);
+export const AutoHiddenSelectedItem = () => <HideDemo></HideDemo>;
 
-class OptionGroupDemo extends React.Component {
-    constructor(props) {
-        super(props);
-        this.handleSearch = this.handleSearch.bind(this);
-        this.state = {
-            groups: [
-                {
-                    label: 'Asia',
-                    children: [
-                        {
-                            label: 'China',
-                            value: 'zhongguo',
-                        },
-                        {
-                            label: 'Koera',
-                            value: 'hanguo',
-                        },
-                    ],
-                },
-                {
-                    label: 'Europe',
-                    children: [
-                        {
-                            label: 'Germany',
-                            value: 'deguo',
-                        },
-                        {
-                            label: 'France',
-                            value: 'faguo',
-                        },
-                    ],
-                },
-                {
-                    label: 'Other',
-                    children: [
-                        {
-                            label: 'vf',
-                            value: 'Sourth',
-                        },
-                    ],
-                },
-            ],
-        };
-    }
+AutoHiddenSelectedItem.story = {
+  name: 'auto hidden selected item',
+};
 
-    handleSearch(input) {
-        let groups = [1, 2, 3].map(i => {
-            return {
-                label: i,
-                // label: Math.random(),
-                children: [10, 20].map(j => {
-                    return {
-                        label: Math.random(),
-                        value: Math.random(),
-                    };
-                }),
-            };
-        });
-        this.setState({
-            groups,
-        });
-    }
+class CustomCreate extends React.Component {
+  constructor(props) {
+    super(props);
+    this.state = {
+      optionList: [
+        {
+          value: 'abc',
+          label: '抖音',
+        },
+        {
+          value: 'hotsoon',
+          label: '火山小视频',
+        },
+        {
+          value: 'pipixia',
+          label: '皮皮虾',
+        },
+        {
+          value: 'toutiao',
+          label: '今日头条',
+        },
+        {
+          value: 0,
+          label: 0,
+        },
+      ],
+      selectedItems: ['fefe'],
+    };
+    this.onChange = this.onChange.bind(this);
+    this.customRender = this.customRender.bind(this);
+    this.search = this.search.bind(this);
+  }
 
-    renderGroup(group) {
-        let options = group.children.map(option => (
-            <Select.Option value={option.value} label={option.label} key={option.label}></Select.Option>
-        ));
-        return <Select.OptGroup label={group.label}>{options}</Select.OptGroup>;
-    }
+  onChange(selectedItems) {
+    console.log(selectedItems); // this.setState({ selectedItems, optionList: [] });
 
-    render() {
-        let { groups } = this.state;
-        return (
-            <>
-                <Select
-                    placeholder=""
-                    style={{
-                        width: 180,
-                    }}
-                    filter
-                    onSearch={this.handleSearch}
-                    remote
-                >
-                    {groups.map(group => this.renderGroup(group))}
-                </Select>
-            </>
-        );
-    }
-}
+    this.setState({
+      selectedItems,
+    }); // this.setState({ optionList: [] });
+  }
 
-stories.add('Select OptionGroup', () => <OptionGroupDemo></OptionGroupDemo>);
+  customRender(v) {
+    return (
+      <>
+        <span>label:{v.label}</span>
+        <span>value:{v.value}</span>
+      </>
+    );
+  }
 
-const BlurDemo = () => {
-    const onBlur = (value, e) => {
-        console.log(value);
-        console.log(e);
+  customCreate(inputValue, isFocus) {
+    let style = {
+      padding: 12,
+      cursor: 'pointer',
+      backgroundColor: isFocus ? 'var(--semi-color-fill-0)' : '#FFF',
     };
+    return <div style={style}>{'create' + inputValue}</div>;
+  }
+
+  search(inputValue) {
+    let length = Math.ceil(Math.random() * 10);
+    let result = Array.from(
+      {
+        length,
+      },
+      (v, i) => {
+        return {
+          value: inputValue + i,
+          label: inputValue + i,
+          type: i + 1,
+        };
+      }
+    );
+    console.log(result); // result = result.concat(selectedOption);
 
-    const onFocus = (value, e) => {
-        console.log(value);
-        console.log(e);
-    };
+    this.setState({
+      optionList: result,
+    });
+  }
 
+  render() {
+    let { optionList, selectedItems } = this.state;
     return (
-        <>
-            <Select
-                filter
-                placeholder=""
-                style={{
-                    width: 180,
-                }}
-                onBlur={onBlur}
-                onFocus={onFocus}
-            >
-                <Select.Option value="zhongguo">China</Select.Option>
-                <Select.Option value="hanguo">Koera</Select.Option>
-                <Select.Option value="deguo">Germany</Select.Option>
-                <Select.Option value="faguo">France</Select.Option>
-            </Select>
-        </>
+      <>
+        <Select
+          defaultValue={['abc']}
+          filter
+          style={{
+            width: 300,
+          }}
+          multiple
+          optionList={optionList}
+          onSearch={this.search}
+          onChange={this.onChange}
+          emptyContent={null} // onChangeWithObject
+        ></Select>
+      </>
     );
-};
+  }
+}
 
-stories.add('Select onBlur/onFocus', () => <BlurDemo></BlurDemo>); // stories.add('BugDemo', () => <BugDemo></BugDemo>);
+export const _CustomCreate = () => <CustomCreate></CustomCreate>;
 
-const AutoAdjustOverflowDemo = () => {
-    const [list, setList] = useState([
-        {
-            value: 'abc',
-            label: '1111',
-        },
+_CustomCreate.story = {
+  name: 'CustomCreate',
+};
+
+class OptionGroupDemo extends React.Component {
+  constructor(props) {
+    super(props);
+    this.handleSearch = this.handleSearch.bind(this);
+    this.state = {
+      groups: [
         {
-            value: 'hotsoon',
-            label: '1112',
+          label: 'Asia',
+          children: [
+            {
+              label: 'China',
+              value: 'zhongguo',
+            },
+            {
+              label: 'Koera',
+              value: 'hanguo',
+            },
+          ],
         },
         {
-            value: 'pipixia',
-            label: '1113',
+          label: 'Europe',
+          children: [
+            {
+              label: 'Germany',
+              value: 'deguo',
+            },
+            {
+              label: 'France',
+              value: 'faguo',
+            },
+          ],
         },
         {
-            value: 'toutiao',
-            label: '1114',
-        },
-    ]);
-
-    const onSearch = () => {
-        let newList = Array.from(
+          label: 'Other',
+          children: [
             {
-                length: Math.floor(Math.random() * 10),
+              label: 'vf',
+              value: 'Sourth',
             },
-            (v, i) => {
-                return {
-                    value: i,
-                    label: i,
-                };
-            }
-        );
-        setList(newList);
-        console.log(newList);
+          ],
+        },
+      ],
     };
+  }
+
+  handleSearch(input) {
+    let groups = [1, 2, 3].map(i => {
+      return {
+        label: i,
+        // label: Math.random(),
+        children: [10, 20].map(j => {
+          return {
+            label: Math.random(),
+            value: Math.random(),
+          };
+        }),
+      };
+    });
+    this.setState({
+      groups,
+    });
+  }
 
+  renderGroup(group) {
+    let options = group.children.map(option => (
+      <Select.Option value={option.value} label={option.label} key={option.label}></Select.Option>
+    ));
+    return <Select.OptGroup label={group.label}>{options}</Select.OptGroup>;
+  }
+
+  render() {
+    let { groups } = this.state;
     return (
-        <div
-            style={{
-                height: 180,
-                margin: 250,
-                border: '1px solid pink',
-            }}
+      <>
+        <Select
+          placeholder=""
+          style={{
+            width: 180,
+          }}
+          filter
+          onSearch={this.handleSearch}
+          remote
         >
-            <Select
-                optionList={list}
-                filter={true}
-                remote={true}
-                onSearch={onSearch}
-                style={{
-                    width: 200,
-                }}
-                multiple
-            />
-        </div>
+          {groups.map(group => this.renderGroup(group))}
+        </Select>
+      </>
     );
+  }
+}
+
+export const SelectOptionGroup = () => <OptionGroupDemo></OptionGroupDemo>;
+
+SelectOptionGroup.story = {
+  name: 'Select OptionGroup',
 };
 
-stories.add('autoAdjustOverflow', () => <AutoAdjustOverflowDemo></AutoAdjustOverflowDemo>);
+const BlurDemo = () => {
+  const onBlur = (value, e) => {
+    console.log(value);
+    console.log(e);
+  };
 
-const AllowCreateWithFilter = () => {
-    const [list, setList] = useState([
-        {
-            value: 'abc',
-            label: 'abc',
-            otherKey: 'abc',
-        },
-        {
-            value: 'hotsoon',
-            label: 'hotsoon',
-            otherKey: 'efg',
-        },
-        {
-            value: 'pipixia',
-            label: 'pipixia',
-            otherKey: 'hij',
-        },
-        {
-            value: 'toutiao',
-            label: 'toutiao',
-            otherKey: 'klm',
-        },
-    ]);
+  const onFocus = (value, e) => {
+    console.log(value);
+    console.log(e);
+  };
 
-    const filter = (sugInput, option) => {
-        let compareKey = option.otherKey ? option.otherKey.toUpperCase() : '';
-        let sug = sugInput.toUpperCase();
-        return compareKey.includes(sug);
-    };
+  return (
+    <>
+      <Select
+        filter
+        placeholder=""
+        style={{
+          width: 180,
+        }}
+        onBlur={onBlur}
+        onFocus={onFocus}
+      >
+        <Select.Option value="zhongguo">China</Select.Option>
+        <Select.Option value="hanguo">Koera</Select.Option>
+        <Select.Option value="deguo">Germany</Select.Option>
+        <Select.Option value="faguo">France</Select.Option>
+      </Select>
+    </>
+  );
+};
 
-    return (
-        <div
-            style={{
-                height: 180,
-                margin: 250,
-            }}
-        >
-            <Select
-                optionList={list}
-                multiple
-                filter={filter}
-                style={{
-                    width: 200,
-                }}
-                allowCreate
-            />
-        </div>
+export const SelectOnBlurOnFocus = () => <BlurDemo></BlurDemo>;
+
+SelectOnBlurOnFocus.story = {
+  name: 'Select onBlur/onFocus',
+};
+
+const AutoAdjustOverflowDemo = () => {
+  const [list, setList] = useState([
+    {
+      value: 'abc',
+      label: '1111',
+    },
+    {
+      value: 'hotsoon',
+      label: '1112',
+    },
+    {
+      value: 'pipixia',
+      label: '1113',
+    },
+    {
+      value: 'toutiao',
+      label: '1114',
+    },
+  ]);
+
+  const onSearch = () => {
+    let newList = Array.from(
+      {
+        length: Math.floor(Math.random() * 10),
+      },
+      (v, i) => {
+        return {
+          value: i,
+          label: i,
+        };
+      }
     );
+    setList(newList);
+    console.log(newList);
+  };
+
+  return (
+    <div
+      style={{
+        height: 180,
+        margin: 250,
+        border: '1px solid pink',
+      }}
+    >
+      <Select
+        optionList={list}
+        filter={true}
+        remote={true}
+        onSearch={onSearch}
+        style={{
+          width: 200,
+        }}
+        multiple
+      />
+    </div>
+  );
+};
+
+export const AutoAdjustOverflow = () => <AutoAdjustOverflowDemo></AutoAdjustOverflowDemo>;
+
+AutoAdjustOverflow.story = {
+  name: 'autoAdjustOverflow',
+};
+
+const AllowCreateWithFilter = () => {
+  const [list, setList] = useState([
+    {
+      value: 'abc',
+      label: 'abc',
+      otherKey: 'abc',
+    },
+    {
+      value: 'hotsoon',
+      label: 'hotsoon',
+      otherKey: 'efg',
+    },
+    {
+      value: 'pipixia',
+      label: 'pipixia',
+      otherKey: 'hij',
+    },
+    {
+      value: 'toutiao',
+      label: 'toutiao',
+      otherKey: 'klm',
+    },
+  ]);
+
+  const filter = (sugInput, option) => {
+    let compareKey = option.otherKey ? option.otherKey.toUpperCase() : '';
+    let sug = sugInput.toUpperCase();
+    return compareKey.includes(sug);
+  };
+
+  return (
+    <div
+      style={{
+        height: 180,
+        margin: 250,
+      }}
+    >
+      <Select
+        optionList={list}
+        multiple
+        filter={filter}
+        style={{
+          width: 200,
+        }}
+        allowCreate
+      />
+    </div>
+  );
 };
 
-stories.add('Filter + allowCreate', () => <AllowCreateWithFilter></AllowCreateWithFilter>);
+export const FilterAllowCreate = () => <AllowCreateWithFilter></AllowCreateWithFilter>;
+
+FilterAllowCreate.story = {
+  name: 'Filter + allowCreate',
+};
 
 const SelectRefDemo = () => {
-    const ref = useRef();
-    const secondRef = useRef();
-    const [open, setOpen] = useState(false);
-    const list = [
-        {
-            value: 'abc',
-            label: 'Abc',
-        },
-        {
-            value: 'hotsoon',
-            label: 'Hotsoon',
-        },
-        {
-            value: 'pipixia',
-            label: 'Pipixia',
-        },
-        {
-            value: 'toutiao',
-            label: 'TooBuzz',
-        },
-    ];
-
-    const change = () => {
-        if (!open) {
-            ref.current.open();
-            setOpen(true);
-        } else {
-            ref.current.close();
-            setOpen(false);
-        }
-    };
+  const ref = useRef();
+  const secondRef = useRef();
+  const [open, setOpen] = useState(false);
+  const list = [
+    {
+      value: 'abc',
+      label: 'Abc',
+    },
+    {
+      value: 'hotsoon',
+      label: 'Hotsoon',
+    },
+    {
+      value: 'pipixia',
+      label: 'Pipixia',
+    },
+    {
+      value: 'toutiao',
+      label: 'TooBuzz',
+    },
+  ];
+
+  const change = () => {
+    if (!open) {
+      ref.current.open();
+      setOpen(true);
+    } else {
+      ref.current.close();
+      setOpen(false);
+    }
+  };
 
-    const focus = () => {
-        ref.current.focus();
-    };
+  const focus = () => {
+    ref.current.focus();
+  };
 
-    const clearInput = () => {
-        ref.current.clearInput();
-    };
+  const clearInput = () => {
+    ref.current.clearInput();
+  };
 
-    const deselectAll = () => {
-        ref.current.deselectAll();
-    };
+  const deselectAll = () => {
+    ref.current.deselectAll();
+  };
 
-    const selectAll = () => {
-        ref.current.selectAll();
-    };
+  const selectAll = () => {
+    ref.current.selectAll();
+  };
 
-    return (
-        <>
-            <h4>onChangeWithObject = false</h4>
-            <Select
-                innerBottomSlot={
-                    <div>
-                        <Space>
-                            <Button onClick={change}>close</Button>
-                            <Button onClick={clearInput}>clearInput</Button>
-                            <Button onClick={deselectAll}>deselectAll</Button>
-                            <Button onClick={selectAll}>selectAll</Button>
-                        </Space>
-                    </div>
-                }
-                ref={ref}
-                onChange={e => console.log(e)}
-                placeholder="Business line"
-                style={{
-                    width: 180,
-                }}
-                optionList={list}
-                filter
-                multiple
-            ></Select>
-            <Space>
-                <Button onClick={change}>open</Button>
-                <Button onClick={focus}>focus</Button>
-                <Button onClick={clearInput}>clearInput</Button>
-                <Button onClick={deselectAll}>deselectAll</Button>
-                <Button onClick={selectAll}>selectAll</Button>
-            </Space>
-            <h4
-                style={{
-                    marginTop: 20,
-                }}
-            >
-                onChangeWithObject = true
-            </h4>
-            <Select
-                innerBottomSlot={
-                    <div>
-                        <Space></Space>
-                    </div>
-                }
-                onChange={e => console.log(e)}
-                onChangeWithObject
-                ref={secondRef}
-                placeholder="Business line"
-                style={{
-                    width: 180,
-                }}
-                optionList={list}
-                filter
-                multiple
-            ></Select>
+  return (
+    <>
+      <h4>onChangeWithObject = false</h4>
+      <Select
+        innerBottomSlot={
+          <div>
             <Space>
-                <Button onClick={() => secondRef.current.deselectAll()}>deselectAll</Button>
-                <Button onClick={() => secondRef.current.selectAll()}>selectAll</Button>
+              <Button onClick={change}>close</Button>
+              <Button onClick={clearInput}>clearInput</Button>
+              <Button onClick={deselectAll}>deselectAll</Button>
+              <Button onClick={selectAll}>selectAll</Button>
             </Space>
-        </>
-    );
+          </div>
+        }
+        ref={ref}
+        onChange={e => console.log(e)}
+        placeholder="Business line"
+        style={{
+          width: 180,
+        }}
+        optionList={list}
+        filter
+        multiple
+      ></Select>
+      <Space>
+        <Button onClick={change}>open</Button>
+        <Button onClick={focus}>focus</Button>
+        <Button onClick={clearInput}>clearInput</Button>
+        <Button onClick={deselectAll}>deselectAll</Button>
+        <Button onClick={selectAll}>selectAll</Button>
+      </Space>
+      <h4
+        style={{
+          marginTop: 20,
+        }}
+      >
+        onChangeWithObject = true
+      </h4>
+      <Select
+        innerBottomSlot={
+          <div>
+            <Space></Space>
+          </div>
+        }
+        onChange={e => console.log(e)}
+        onChangeWithObject
+        ref={secondRef}
+        placeholder="Business line"
+        style={{
+          width: 180,
+        }}
+        optionList={list}
+        filter
+        multiple
+      ></Select>
+      <Space>
+        <Button onClick={() => secondRef.current.deselectAll()}>deselectAll</Button>
+        <Button onClick={() => secondRef.current.selectAll()}>selectAll</Button>
+      </Space>
+    </>
+  );
 };
 
-stories.add('ref', () => <SelectRefDemo />);
-stories.add(`custom trigger`, () => <CustomTrigger />); 
+export const Ref = () => <SelectRefDemo />;
 
-class VirtualizeDemo extends React.Component {
-    constructor(props) {
-        super(props);
-        // this.handleSearch = this.handleSearch.bind(this);
-        let newOptions = Array.from({ length: 1000 }, (v, i) => ({ label: `option-${i}`, value: i }));
-        this.state = {
-            optionList: newOptions,
-        };
-    }
-    render() {
-        let { groups, optionList } = this.state;
-        let virtualize = {
-            height: 300,
-            widht: '100%',
-            itemSize: 36,
-        };
-        return (
-            <>
-                <Select
-                    placeholder=""
-                    style={{ width: 180 }}
-                    filter
-                    onSearch={this.handleSearch}
-                    virtualize={virtualize}
-                    optionList={optionList}
-                ></Select>
-            </>
-        );
-    }
+Ref.story = {
+  name: 'ref',
+};
+
+export const CustomTriggerDemo = () => <CustomTrigger />;
+CustomTriggerDemo.story = {
+  name: 'custom trigger'
 }
-stories.add(`virtualize select`, () => <VirtualizeDemo />);
 
-const SelectPosition = () => {
+class VirtualizeClassDemo extends React.Component {
+  constructor(props) {
+    super(props);
+    // this.handleSearch = this.handleSearch.bind(this);
+    let newOptions = Array.from({ length: 1000 }, (v, i) => ({ label: `option-${i}`, value: i }));
+    this.state = {
+      optionList: newOptions,
+    };
+  }
+  render() {
+    let { groups, optionList } = this.state;
+    let virtualize = {
+      height: 300,
+      widht: '100%',
+      itemSize: 36,
+    };
     return (
-        <div
-            style={{
-                height: 500,
-                border: '1px solid red',
-                overflow: 'auto',
-            }}
-        >
-            <p>p</p>
-            <p>p</p>
-            <p>p</p>
-            <p>p</p>
-            <p>p</p>
-            <p>p</p>
-            <p>p</p>
-            <p>p</p>
-            <p>p</p>
-            <p>p</p>
-            <p>p</p>
-            <p>p</p>
-            <p>p</p>
-            <p>p</p>
-            <p>p</p>
-            <p>p</p>
-            <p>p</p>
-            <p>p</p>
-            <p>p</p>
-            <p>p</p>
-            <p>p</p>
-            <p>p</p>
-            <p>p</p>
-            <Select
-                defaultValue="abc"
-                style={{
-                    width: 120,
-                }}
-            >
-                <Option value="abc">抖音</Option>
-                <Option value="hotsoon">火山</Option>
-                <Option value="pipixia" disabled>
-                    皮皮虾
-                </Option>
-                <Option value="xigua">西瓜视频</Option>
-            </Select>
-            <p>p</p>
-            <p>p</p>
-            <p>p</p>
-            <p>p</p>
-            <p>p</p>
-            <p>p</p>
-            <p>p</p>
-            <p>p</p>
-            <p>p</p>
-            <p>p</p>
-            <p>p</p>
-            <p>p</p>
-            <p>p</p>
-            <p>p</p>
-            <p>p</p>
-            <p>p</p>
-            <p>p</p>
-            <p>p</p>
-            <p>p</p>
-            <p>p</p>
-            <p>p</p>
-            <p>p</p>
-            <p>p</p>
-            <p>p</p>
-            <p>p</p>
-            <p>p</p>
-            <p>p</p>
-            <p>p</p>
-            <p>p</p>
-            <p>p</p>
-            <p>p</p>
-            <p>p</p>
-            <p>p</p>
-            <p>p</p>
-            <p>p</p>
-            <p>p</p>
-            <p>p</p>
-            <p>p</p>
-            <p>p</p>
-            <p>p</p>
-            <p>p</p>
-            <p>p</p>
-        </div>
+      <>
+        <Select
+          placeholder=""
+          style={{ width: 180 }}
+          filter
+          onSearch={this.handleSearch}
+          virtualize={virtualize}
+          optionList={optionList}
+        ></Select>
+      </>
     );
+  }
+}
+
+export const VirtualizeDemo = () => <VirtualizeClassDemo />;
+
+VirtualizeDemo.story = {
+  name: 'virtualize select'
+}
+
+
+const SelectPosition = () => {
+  return (
+    <div
+      style={{
+        height: 500,
+        border: '1px solid red',
+        overflow: 'auto',
+      }}
+    >
+      <p>p</p>
+      <p>p</p>
+      <p>p</p>
+      <p>p</p>
+      <p>p</p>
+      <p>p</p>
+      <p>p</p>
+      <p>p</p>
+      <p>p</p>
+      <p>p</p>
+      <p>p</p>
+      <p>p</p>
+      <p>p</p>
+      <p>p</p>
+      <p>p</p>
+      <p>p</p>
+      <p>p</p>
+      <p>p</p>
+      <p>p</p>
+      <p>p</p>
+      <p>p</p>
+      <p>p</p>
+      <p>p</p>
+      <Select
+        defaultValue="abc"
+        style={{
+          width: 120,
+        }}
+      >
+        <Option value="abc">抖音</Option>
+        <Option value="hotsoon">火山</Option>
+        <Option value="pipixia" disabled>
+          皮皮虾
+        </Option>
+        <Option value="xigua">西瓜视频</Option>
+      </Select>
+      <p>p</p>
+      <p>p</p>
+      <p>p</p>
+      <p>p</p>
+      <p>p</p>
+      <p>p</p>
+      <p>p</p>
+      <p>p</p>
+      <p>p</p>
+      <p>p</p>
+      <p>p</p>
+      <p>p</p>
+      <p>p</p>
+      <p>p</p>
+      <p>p</p>
+      <p>p</p>
+      <p>p</p>
+      <p>p</p>
+      <p>p</p>
+      <p>p</p>
+      <p>p</p>
+      <p>p</p>
+      <p>p</p>
+      <p>p</p>
+      <p>p</p>
+      <p>p</p>
+      <p>p</p>
+      <p>p</p>
+      <p>p</p>
+      <p>p</p>
+      <p>p</p>
+      <p>p</p>
+      <p>p</p>
+      <p>p</p>
+      <p>p</p>
+      <p>p</p>
+      <p>p</p>
+      <p>p</p>
+      <p>p</p>
+      <p>p</p>
+      <p>p</p>
+      <p>p</p>
+    </div>
+  );
 };
 
-stories.add(`Select position problem`, () => <SelectPosition />);
+export { SelectPosition };
+SelectPosition.story = {
+  name: 'Select position problem'
+}
 
 const RenderOptionDemo = () => {
-    const renderOptionItem = renderProps => {
-        const {
-            disabled,
-            selected,
-            label,
-            value,
-            focused,
-            className,
-            style,
-            onMouseEnter,
-            onClick,
-            empty,
-            emptyContent,
-            ...rest
-        } = renderProps;
-        const optionCls = classNames({
-            ['custom-option-render']: true,
-            ['custom-option-render-focused']: focused,
-            ['custom-option-render-disabled']: disabled,
-            ['custom-option-render-selected']: selected,
-        }); // Notice:
-        // 1.props传入的style需在wrapper dom上进行消费,否则在虚拟化场景下会无法正常使用
-        // 2.选中(selected)、聚焦(focused)、禁用(disabled)等状态的样式需自行加上,你可以从props中获取到相对的boolean值
-        // 3.onMouseEnter需在wrapper dom上绑定,否则上下键盘操作时显示会有问题
-
-        return (
-            <div style={style} className={optionCls} onClick={() => onClick()} onMouseEnter={e => onMouseEnter()}>
-                <Checkbox checked={selected} />
-                <div className="option-right">{label}</div>
-            </div>
-        );
-    };
+  const renderOptionItem = renderProps => {
+    const {
+      disabled,
+      selected,
+      label,
+      value,
+      focused,
+      className,
+      style,
+      onMouseEnter,
+      onClick,
+      empty,
+      emptyContent,
+      ...rest
+    } = renderProps;
+    const optionCls = classNames({
+      ['custom-option-render']: true,
+      ['custom-option-render-focused']: focused,
+      ['custom-option-render-disabled']: disabled,
+      ['custom-option-render-selected']: selected,
+    }); // Notice:
+    // 1.props传入的style需在wrapper dom上进行消费,否则在虚拟化场景下会无法正常使用
+    // 2.选中(selected)、聚焦(focused)、禁用(disabled)等状态的样式需自行加上,你可以从props中获取到相对的boolean值
+    // 3.onMouseEnter需在wrapper dom上绑定,否则上下键盘操作时显示会有问题
 
     return (
-        <>
-            <Select
-                filter
-                dropdownClassName="components-select-demo-renderOptionItem"
-                optionList={optionList}
-                style={{
-                    width: 300,
-                }}
-                renderOptionItem={renderOptionItem}
-            />
-            <br />
-            <br />
-            <Select
-                filter
-                multiple
-                dropdownClassName="components-select-demo-renderOptionItem"
-                optionList={optionList}
-                style={{
-                    width: 450,
-                }}
-                renderOptionItem={renderOptionItem}
-            />
-        </>
+      <div
+        style={style}
+        className={optionCls}
+        onClick={() => onClick()}
+        onMouseEnter={e => onMouseEnter()}
+      >
+        <Checkbox checked={selected} />
+        <div className="option-right">{label}</div>
+      </div>
     );
+  };
+
+  return (
+    <>
+      <Select
+        filter
+        dropdownClassName="components-select-demo-renderOptionItem"
+        optionList={optionList}
+        style={{
+          width: 300,
+        }}
+        renderOptionItem={renderOptionItem}
+      />
+      <br />
+      <br />
+      <Select
+        filter
+        multiple
+        dropdownClassName="components-select-demo-renderOptionItem"
+        optionList={optionList}
+        style={{
+          width: 450,
+        }}
+        renderOptionItem={renderOptionItem}
+      />
+    </>
+  );
 };
 
-stories.add('renderOptionItem', () => <RenderOptionDemo />);
+export const RenderOptionItem = () => <RenderOptionDemo />;
+
+RenderOptionItem.story = {
+  name: 'renderOptionItem',
+};
 
 const FilterDefaultOpen = () => {
-    const [value1, setValue1] = useState('a-1');
-    return (
-        <>
-            <Select
-                placeholder=""
-                style={{
-                    width: 180,
-                }}
-                filter
-                defaultOpen
-            >
-                <Select.OptGroup label="Asia">
-                    <Select.Option value="a-1">China</Select.Option>
-                    <Select.Option value="a-2">Koera</Select.Option>
-                </Select.OptGroup>
-                <Select.OptGroup label="Europe">
-                    <Select.Option value="b-1">Germany</Select.Option>
-                    <Select.Option value="b-2">France</Select.Option>
-                </Select.OptGroup>
-                <Select.OptGroup label="South America">
-                    <Select.Option value="c-1">Peru</Select.Option>
-                </Select.OptGroup>
-            </Select>
-            <Select
-                placeholder=""
-                style={{
-                    width: 180,
-                    marginLeft: 20,
-                }}
-                filter
-                defaultOpen
-                defaultValue="a-2"
-            >
-                <Select.OptGroup label="Asia">
-                    <Select.Option value="a-1">China</Select.Option>
-                    <Select.Option value="a-2">Koera</Select.Option>
-                </Select.OptGroup>
-                <Select.OptGroup label="Europe">
-                    <Select.Option value="b-1">Germany</Select.Option>
-                    <Select.Option value="b-2">France</Select.Option>
-                </Select.OptGroup>
-                <Select.OptGroup label="South America">
-                    <Select.Option value="c-1">Peru</Select.Option>
-                </Select.OptGroup>
-            </Select>
-            <Select
-                placeholder=""
-                style={{
-                    width: 180,
-                    marginLeft: 20,
-                }}
-                filter
-                defaultOpen
-                value={value1}
-                onChange={val => setValue1(val)}
-            >
-                <Select.Option value="a-1">China</Select.Option>
-                <Select.Option value="a-2">Koera</Select.Option>
-                <Select.Option value="b-1">Germany</Select.Option>
-                <Select.Option value="b-2">France</Select.Option>
-                <Select.Option value="c-1">Peru</Select.Option>
-            </Select>
-        </>
-    );
+  const [value1, setValue1] = useState('a-1');
+  return (
+    <>
+      <Select
+        placeholder=""
+        style={{
+          width: 180,
+        }}
+        filter
+        defaultOpen
+      >
+        <Select.OptGroup label="Asia">
+          <Select.Option value="a-1">China</Select.Option>
+          <Select.Option value="a-2">Koera</Select.Option>
+        </Select.OptGroup>
+        <Select.OptGroup label="Europe">
+          <Select.Option value="b-1">Germany</Select.Option>
+          <Select.Option value="b-2">France</Select.Option>
+        </Select.OptGroup>
+        <Select.OptGroup label="South America">
+          <Select.Option value="c-1">Peru</Select.Option>
+        </Select.OptGroup>
+      </Select>
+      <Select
+        placeholder=""
+        style={{
+          width: 180,
+          marginLeft: 20,
+        }}
+        filter
+        defaultOpen
+        defaultValue="a-2"
+      >
+        <Select.OptGroup label="Asia">
+          <Select.Option value="a-1">China</Select.Option>
+          <Select.Option value="a-2">Koera</Select.Option>
+        </Select.OptGroup>
+        <Select.OptGroup label="Europe">
+          <Select.Option value="b-1">Germany</Select.Option>
+          <Select.Option value="b-2">France</Select.Option>
+        </Select.OptGroup>
+        <Select.OptGroup label="South America">
+          <Select.Option value="c-1">Peru</Select.Option>
+        </Select.OptGroup>
+      </Select>
+      <Select
+        placeholder=""
+        style={{
+          width: 180,
+          marginLeft: 20,
+        }}
+        filter
+        defaultOpen
+        value={value1}
+        onChange={val => setValue1(val)}
+      >
+        <Select.Option value="a-1">China</Select.Option>
+        <Select.Option value="a-2">Koera</Select.Option>
+        <Select.Option value="b-1">Germany</Select.Option>
+        <Select.Option value="b-2">France</Select.Option>
+        <Select.Option value="c-1">Peru</Select.Option>
+      </Select>
+    </>
+  );
 };
 
-stories.add(`Filter + defaultOpen`, () => <FilterDefaultOpen />); // const CustomSelect = React.forwardRef((props, ref) => {
-//     const { fieldRef, ...rest } = props;
-//     return <Select {...rest} ref={fieldRef} />
-// });
+export { FilterDefaultOpen };
+FilterDefaultOpen.story = {
+  name: 'Filter + defaultOpen'
+};
 
 const CustomSelect = props => {
-    const { fieldRef, ...rest } = props;
-    return <Select {...rest} ref={fieldRef} />;
+  const { fieldRef, ...rest } = props;
+  return <Select {...rest} ref={fieldRef} />;
 };
 
 const CustomFieldSelect = withField(CustomSelect);
 
 const RefDemo = () => {
-    const fieldRef = useRef(null);
+  const fieldRef = useRef(null);
+
+  const onChange = () => {
+    console.log(fieldRef);
+    fieldRef.current.open();
+    debugger;
+  };
+
+  return (
+    <Form>
+      <CustomFieldSelect field="test" initValue="se" fieldRef={fieldRef}></CustomFieldSelect>
+      <Button onClick={onChange}>change</Button>
+    </Form>
+  );
+};
 
-    const onChange = () => {
-        console.log(fieldRef);
-        fieldRef.current.open();
-        debugger;
-    };
+export const RefFieldDemo = () => <RefDemo />;
 
-    return (
-        <Form>
-            <CustomFieldSelect field="test" initValue="se" fieldRef={fieldRef}></CustomFieldSelect>
-            <Button onClick={onChange}>change</Button>
-        </Form>
-    );
+RefFieldDemo.story = {
+  name: 'Ref field demo',
 };
 
-stories.add('Ref field demo', () => <RefDemo />);
-
 const ValueZeroDemo = () => {
-    const list = [
-        {
-            value: 6,
-            label: '抖音小视频',
-            otherKey: 0,
-        },
-        {
-            value: 1,
-            label: '火山小视频',
-            disabled: true,
-            otherKey: 1,
-        },
-        {
-            value: 'pipixia',
-            label: '皮皮虾',
-            otherKey: 2,
-        },
-        {
-            value: 'toutiao',
-            label: '今日头条',
-            otherKey: 3,
-        },
-    ];
-    return (
-        <Select
-            placeholder="请选择业务线"
-            style={{
-                width: 180,
-            }}
-            optionList={list}
-            value={0}
-            renderSelectedItem={option => option.label + 1}
-        ></Select>
-    );
+  const list = [
+    {
+      value: 6,
+      label: '抖音小视频',
+      otherKey: 0,
+    },
+    {
+      value: 1,
+      label: '火山小视频',
+      disabled: true,
+      otherKey: 1,
+    },
+    {
+      value: 'pipixia',
+      label: '皮皮虾',
+      otherKey: 2,
+    },
+    {
+      value: 'toutiao',
+      label: '今日头条',
+      otherKey: 3,
+    },
+  ];
+  return (
+    <Select
+      placeholder="请选择业务线"
+      style={{
+        width: 180,
+      }}
+      optionList={list}
+      value={0}
+      renderSelectedItem={option => option.label + 1}
+    ></Select>
+  );
 };
 
-stories.add('value=0', () => <ValueZeroDemo />);
+export const Value0 = () => <ValueZeroDemo />;
+
+Value0.story = {
+  name: 'value=0',
+};
 
 const Highlight = () => {
-    const searchWords = ['do', 'dollar'];
-    const sourceString = 'aaa do dollar aaa';
-    const result = getHighLightTextHTML({
-        searchWords,
-        sourceString,
-    });
-    const result2 = getHighLightTextHTML({
-        searchWords: ['z'],
-        sourceString: 'aaazaaazaaa',
-    });
-    return result2;
+  const searchWords = ['do', 'dollar'];
+  const sourceString = 'aaa do dollar aaa';
+  const result = getHighLightTextHTML({
+    searchWords,
+    sourceString,
+  });
+  const result2 = getHighLightTextHTML({
+    searchWords: ['z'],
+    sourceString: 'aaazaaazaaa',
+  });
+  return result2;
 };
 
-stories.add('highlight', () => <Highlight />);
+export const _Highlight = () => <Highlight />;
 
-stories.add('scroll into view', () => (
-    <>
-        <div>
-            <p>single selection</p>
-            <Select defaultValue='option-11' defaultOpen style={{ marginBottom: 300, width: 120 }}>
-                {new Array(50).fill(null).map((item, idx) => (
-                    <Option value={`${idx}`} key={idx}>{`option-${idx}`}</Option>
-                ))}
-            </Select>
-            <p>single selection with no selected item</p>
-            <Select style={{ marginBottom: 300, width: 120 }}>
-                {new Array(50).fill(null).map((item, idx) => (
-                    <Option value={`${idx}`} key={idx}>{`option-${idx}`}</Option>
-                ))}
-            </Select>
-            <p>The selected node is the last</p>
-            <Select defaultValue='option-49' defaultOpen style={{ marginBottom: 300, width: 120 }}>
-                {new Array(50).fill(null).map((item, idx) => (
-                    <Option value={`${idx}`} key={idx}>{`option-${idx}`}</Option>
-                ))}
-            </Select>
-            <p>The selected node is the first</p>
-            <Select defaultValue='option-0' style={{ marginBottom: 300, width: 120 }}>
-                {new Array(50).fill(null).map((item, idx) => (
-                    <Option value={`${idx}`} key={idx}>{`option-${idx}`}</Option>
-                ))}
-            </Select>
-            <p>multiple selection</p>
-            <Select defaultValue={['option-25', 'option-9']} multiple style={{ marginBottom: 300, width: 220 }}>
-                {new Array(30).fill(null).map((item, idx) => (
-                    <Option value={`${idx}`} key={idx}>{`option-${idx}`}</Option>
-                ))}
-            </Select>
-            <p>multiple selection with no selected item</p>
-            <Select multiple style={{ marginBottom: 300, width: 220 }}>
-                {new Array(30).fill(null).map((item, idx) => (
-                    <Option value={`${idx}`} key={idx}>{`option-${idx}`}</Option>
-                ))}
-            </Select>
-        </div>
-    </>
-));
+_Highlight.story = {
+  name: 'highlight',
+};
+
+export const ScrollIntoView = () => (
+  <>
+    <div>
+      <p>single selection</p>
+      <Select defaultValue="option-11" defaultOpen style={{ marginBottom: 300, width: 120 }}>
+        {new Array(50).fill(null).map((item, idx) => (
+          <Option value={`${idx}`} key={idx}>{`option-${idx}`}</Option>
+        ))}
+      </Select>
+      <p>single selection with no selected item</p>
+      <Select style={{ marginBottom: 300, width: 120 }}>
+        {new Array(50).fill(null).map((item, idx) => (
+          <Option value={`${idx}`} key={idx}>{`option-${idx}`}</Option>
+        ))}
+      </Select>
+      <p>The selected node is the last</p>
+      <Select defaultValue="option-49" defaultOpen style={{ marginBottom: 300, width: 120 }}>
+        {new Array(50).fill(null).map((item, idx) => (
+          <Option value={`${idx}`} key={idx}>{`option-${idx}`}</Option>
+        ))}
+      </Select>
+      <p>The selected node is the first</p>
+      <Select defaultValue="option-0" style={{ marginBottom: 300, width: 120 }}>
+        {new Array(50).fill(null).map((item, idx) => (
+          <Option value={`${idx}`} key={idx}>{`option-${idx}`}</Option>
+        ))}
+      </Select>
+      <p>multiple selection</p>
+      <Select
+        defaultValue={['option-25', 'option-9']}
+        multiple
+        style={{ marginBottom: 300, width: 220 }}
+      >
+        {new Array(30).fill(null).map((item, idx) => (
+          <Option value={`${idx}`} key={idx}>{`option-${idx}`}</Option>
+        ))}
+      </Select>
+      <p>multiple selection with no selected item</p>
+      <Select multiple style={{ marginBottom: 300, width: 220 }}>
+        {new Array(30).fill(null).map((item, idx) => (
+          <Option value={`${idx}`} key={idx}>{`option-${idx}`}</Option>
+        ))}
+      </Select>
+    </div>
+  </>
+);
+
+ScrollIntoView.story = {
+  name: 'scroll into view',
+};

+ 336 - 311
packages/semi-ui/sideSheet/_story/sideSheet.stories.js

@@ -1,354 +1,379 @@
 import React, { useState } from 'react';
-import { storiesOf } from '@storybook/react';
 
 import SideSheet from '../index';
-import {
-    Select,
-    Button,
-    Tooltip,
-    RadioGroup,
-    Radio,
-} from '../../index';
+import { Select, Button, Tooltip, RadioGroup, Radio } from '../../index';
 
-
-const stories = storiesOf('SideSheet', module);
-
-// stories.addDecorator(withKnobs);;
+export default {
+  title: 'SideSheet',
+  parameters: {
+    chromatic: { disableSnapshot: true },
+  },
+}
 
 const BasicSide = props => {
-    const [visible, setVisible] = useState(false);
-
-    const handleCancel = e => {
-        console.log('cancelling')
-        setVisible(false);
-    };
-
-    return (
-        <React.Fragment>
-            <Button onClick={() => setVisible(true)}>show sideSheet</Button>
-            <SideSheet visible={visible} onCancel={handleCancel}>12333</SideSheet>
-        </React.Fragment>
-    );
+  const [visible, setVisible] = useState(false);
+
+  const handleCancel = e => {
+    console.log('cancelling');
+    setVisible(false);
+  };
+
+  return (
+    <React.Fragment>
+      <Button onClick={() => setVisible(true)}>show sideSheet</Button>
+      <SideSheet visible={visible} onCancel={handleCancel}>
+        12333
+      </SideSheet>
+    </React.Fragment>
+  );
 };
 
-stories.add('side sheet left', () => <BasicSide />);
+export const SideSheetLeft = () => <BasicSide />;
+
+SideSheetLeft.story = {
+  name: 'side sheet left',
+};
 
 const PosBasicSide = props => {
-    const [visible, setVisible] = useState(false);
-
-    const handleCancel = e => {
-        setVisible(false);
-    };
-
-    return (
-        <React.Fragment>
-            <Button onClick={() => setVisible(true)}>show sideSheet</Button>
-            <SideSheet visible={visible} placement={'bottom'} onCancel={handleCancel}>12333</SideSheet>
-        </React.Fragment>
-    );
+  const [visible, setVisible] = useState(false);
+
+  const handleCancel = e => {
+    setVisible(false);
+  };
+
+  return (
+    <React.Fragment>
+      <Button onClick={() => setVisible(true)}>show sideSheet</Button>
+      <SideSheet visible={visible} placement={'bottom'} onCancel={handleCancel}>
+        12333
+      </SideSheet>
+    </React.Fragment>
+  );
 };
 
-stories.add('side sheet', () => <PosBasicSide />);
+export const _SideSheet = () => <PosBasicSide />;
+
+_SideSheet.story = {
+  name: 'side sheet',
+};
 
 const SideMask = props => {
-    const [visible, setVisible] = useState(false);
-
-    const handleCancel = e => {
-        setVisible(false);
-    };
-
-    return (
-        <React.Fragment>
-            <Button onClick={() => setVisible(true)}>show sideSheet</Button>
-            <SideSheet
-                visible={visible}
-                placement={'bottom'}
-                onCancel={handleCancel}
-                maskClosable={false}
-            >
-                12333
-            </SideSheet>
-        </React.Fragment>
-    );
+  const [visible, setVisible] = useState(false);
+
+  const handleCancel = e => {
+    setVisible(false);
+  };
+
+  return (
+    <React.Fragment>
+      <Button onClick={() => setVisible(true)}>show sideSheet</Button>
+      <SideSheet
+        visible={visible}
+        placement={'bottom'}
+        onCancel={handleCancel}
+        maskClosable={false}
+      >
+        12333
+      </SideSheet>
+    </React.Fragment>
+  );
 };
 
-stories.add('side sheet mask', () => <SideMask />);
+export const SideSheetMask = () => <SideMask />;
 
+SideSheetMask.story = {
+  name: 'side sheet mask',
+};
 
 const Test2 = () => {
-    const [visible, setVisible] = useState(false);
-    const [visible2, setVisible2] = useState(false);
-    const handleCancel = e => {
-        setVisible(false);
-    };
-
-    const handleCancel2 = e => {
-        setVisible2(false);
-    };
-
-    return (
-        <>
-            <Button onClick={() => setVisible(true)} > show sideSheet </Button>
-            <SideSheet
-                visible={visible}
-                placement={'bottom'}
-                onCancel={handleCancel}
-            >
-                <Button onClick={() => setVisible2(true)}>show sideSheet2 </Button>
-                <SideSheet
-                    visible={visible2}
-                    placement={'bottom'}
-                    onCancel={handleCancel2}
-                    height='200px'
-                />
-            </SideSheet>
-        </>
-    );
+  const [visible, setVisible] = useState(false);
+  const [visible2, setVisible2] = useState(false);
+  const handleCancel = e => {
+    setVisible(false);
+  };
+
+  const handleCancel2 = e => {
+    setVisible2(false);
+  };
+
+  return (
+    <>
+      <Button onClick={() => setVisible(true)}> show sideSheet </Button>
+      <SideSheet visible={visible} placement={'bottom'} onCancel={handleCancel}>
+        <Button onClick={() => setVisible2(true)}>show sideSheet2 </Button>
+        <SideSheet
+          visible={visible2}
+          placement={'bottom'}
+          onCancel={handleCancel2}
+          height="200px"
+        />
+      </SideSheet>
+    </>
+  );
 };
 
-stories.add('sidesheet in sidesheet', () => < Test2 />);
+export const SidesheetInSidesheet = () => <Test2 />;
+
+SidesheetInSidesheet.story = {
+  name: 'sidesheet in sidesheet',
+};
 
 const Blocking = () => {
-    const [visible, setVisible] = useState(false);
-    const [placement, setPlacement] = useState('right');
-    const handleCancel = e => {
-        setVisible(false);
-    };
-    const show = () => {
-        setVisible(true);
-    }
-
-    const onSelect = e => {
-        setPlacement(e.target.value)
-    }
-    return (
-        <>
-            <RadioGroup onChange={(e) => onSelect(e)} value={placement}>
-                <Radio value={'right'}>right</Radio>
-                <Radio value={'left'}>left</Radio>
-                <Radio value={'top'}>top</Radio>
-                <Radio value={'bottom'}>bottom</Radio>
-            </RadioGroup>
-            <p>
-                jklasjdkfljaskljdfklajksdljfkl;ajklsdjfk;lajksldjfklajskdlfjajsdlf;jaklsjdfkljaklsdjflajsdfjakljsdkl;fja;sd
-            </p>
-            <br />
-            <br />
-            <Button onClick={() => show()}>Open SideSheet</Button>
-            <SideSheet
-                title="自定义位置的侧边栏"
-                visible={visible}
-                placement={placement}
-                onCancel={() => handleCancel()}
-                mask={false}
-            >
-                <p>This is the content of a basic sidesheet.</p>
-                <p>Here is more content...</p>
-            </SideSheet>
-        </>
-    );
-}
+  const [visible, setVisible] = useState(false);
+  const [placement, setPlacement] = useState('right');
+  const handleCancel = e => {
+    setVisible(false);
+  };
+  const show = () => {
+    setVisible(true);
+  };
+
+  const onSelect = e => {
+    setPlacement(e.target.value);
+  };
+  return (
+    <>
+      <RadioGroup onChange={e => onSelect(e)} value={placement}>
+        <Radio value={'right'}>right</Radio>
+        <Radio value={'left'}>left</Radio>
+        <Radio value={'top'}>top</Radio>
+        <Radio value={'bottom'}>bottom</Radio>
+      </RadioGroup>
+      <p>
+        jklasjdkfljaskljdfklajksdljfkl;ajklsdjfk;lajksldjfklajskdlfjajsdlf;jaklsjdfkljaklsdjflajsdfjakljsdkl;fja;sd
+      </p>
+      <br />
+      <br />
+      <Button onClick={() => show()}>Open SideSheet</Button>
+      <SideSheet
+        title="自定义位置的侧边栏"
+        visible={visible}
+        placement={placement}
+        onCancel={() => handleCancel()}
+        mask={false}
+      >
+        <p>This is the content of a basic sidesheet.</p>
+        <p>Here is more content...</p>
+      </SideSheet>
+    </>
+  );
+};
 
-stories.add('sidesheet non-blocking', () => <Blocking />);
+export const SidesheetNonBlocking = () => <Blocking />;
 
+SidesheetNonBlocking.story = {
+  name: 'sidesheet non-blocking',
+};
 
 const Popup = () => {
-    const [visible, setVisible] = useState(false);
-    const [placement, setPlacement] = useState('right');
-    const handleCancel = e => {
-        setVisible(false);
-    };
-
-    const onSelect = e => {
-        setPlacement(e.target.value)
-    }
-    return (
-        <div
-            style={{
-                height: 200,
-                overflow: 'hidden',
-                position: 'relative',
-                border: '1px solid #ebedf0',
-                borderRadius: 2,
-                padding: 48,
-                textAlign: 'center',
-                background: '#fafafa',
-            }}
-            className='sidesheet-container'
-        >
-            Render in this
-            <div style={{ marginTop: 16 }}>
-                <Button onClick={() => setVisible(true)} > show sideSheet </Button>
-                <RadioGroup onChange={(e) => onSelect(e)} value={placement}>
-                    <Radio value={'right'}>right</Radio>
-                    <Radio value={'left'}>left</Radio>
-                    <Radio value={'top'}>top</Radio>
-                    <Radio value={'bottom'}>bottom</Radio>
-                </RadioGroup>
-            </div>
-            <SideSheet
-                visible={visible}
-                title='sideSheet'
-                height='100px'
-                placement={'right'}
-                onCancel={handleCancel}
-                placement={placement}
-                getPopupContainer={() => document.querySelector('.sidesheet-container')}
-            >
-                <p>Some contents...</p>
-                <p>Some contents...</p>
-                <p>Some contents...</p>
-                <p>Some contents...</p>
-                <p>Some contents...</p>
-                <p>Some contents...</p>
-                <p>Some contents...</p>
-                <p>Some contents...</p>
-                <p>Some contents...</p>
-                <p>Some contents...</p>
-                <p>Some contents...</p>
-                <p>Some contents...</p>
-                <p>Some contents...</p>
-                <p>Some contents...</p>
-                <p>Some contents...</p>
-                <p>Some contents...</p>
-            </SideSheet>
-        </div>
-
-    );
+  const [visible, setVisible] = useState(false);
+  const [placement, setPlacement] = useState('right');
+  const handleCancel = e => {
+    setVisible(false);
+  };
+
+  const onSelect = e => {
+    setPlacement(e.target.value);
+  };
+  return (
+    <div
+      style={{
+        height: 200,
+        overflow: 'hidden',
+        position: 'relative',
+        border: '1px solid #ebedf0',
+        borderRadius: 2,
+        padding: 48,
+        textAlign: 'center',
+        background: '#fafafa',
+      }}
+      className="sidesheet-container"
+    >
+      Render in this
+      <div style={{ marginTop: 16 }}>
+        <Button onClick={() => setVisible(true)}> show sideSheet </Button>
+        <RadioGroup onChange={e => onSelect(e)} value={placement}>
+          <Radio value={'right'}>right</Radio>
+          <Radio value={'left'}>left</Radio>
+          <Radio value={'top'}>top</Radio>
+          <Radio value={'bottom'}>bottom</Radio>
+        </RadioGroup>
+      </div>
+      <SideSheet
+        visible={visible}
+        title="sideSheet"
+        height="100px"
+        placement={'right'}
+        onCancel={handleCancel}
+        placement={placement}
+        getPopupContainer={() => document.querySelector('.sidesheet-container')}
+      >
+        <p>Some contents...</p>
+        <p>Some contents...</p>
+        <p>Some contents...</p>
+        <p>Some contents...</p>
+        <p>Some contents...</p>
+        <p>Some contents...</p>
+        <p>Some contents...</p>
+        <p>Some contents...</p>
+        <p>Some contents...</p>
+        <p>Some contents...</p>
+        <p>Some contents...</p>
+        <p>Some contents...</p>
+        <p>Some contents...</p>
+        <p>Some contents...</p>
+        <p>Some contents...</p>
+        <p>Some contents...</p>
+      </SideSheet>
+    </div>
+  );
 };
 
-stories.add('sidesheet getpopupcontanier', () => <Popup />);
+export const SidesheetGetpopupcontanier = () => <Popup />;
 
+SidesheetGetpopupcontanier.story = {
+  name: 'sidesheet getpopupcontanier',
+};
 
 const Combox = () => {
-    const [visible, setVisible] = useState(false);
-    const [placement, setPlacement] = useState('right');
-    const handleCancel = e => {
-        setVisible(false);
-    };
-
-    const onSelect = e => {
-        setPlacement(e.target.value)
-    }
-    return (
-        <div
-            style={{
-                height: 200,
-                overflow: 'hidden',
-                position: 'relative',
-                border: '1px solid #ebedf0',
-                borderRadius: 2,
-                padding: 48,
-                textAlign: 'center',
-                background: '#fafafa',
-            }}
-            className='sidesheet-container'
-        >
-            Render in this
-            <div style={{ marginTop: 16 }}>
-                <Button onClick={() => setVisible(true)} > show sideSheet </Button>
-                <RadioGroup onChange={(e) => onSelect(e)} value={placement}>
-                    <Radio value={'right'}>right</Radio>
-                    <Radio value={'left'}>left</Radio>
-                    <Radio value={'top'}>top</Radio>
-                    <Radio value={'bottom'}>bottom</Radio>
-                </RadioGroup>
-            </div>
-            <SideSheet
-                visible={visible}
-                title='sideSheet'
-                height='100px'
-                placement={'right'}
-                onCancel={handleCancel}
-                placement={placement}
-                mask={false}
-                bodyStyle={{ overflow: 'auto', height: 200 }}
-                getPopupContainer={() => document.querySelector('.sidesheet-container')}
-            >
-                <p>Some contents...</p>
-                <p>Some contents...</p>
-                <p>Some contents...</p>
-                <p>Some contents...</p>
-                <p>Some contents...</p>
-                <p>Some contents...</p>
-                <p>Some contents...</p>
-                <p>Some contents...</p>
-                <p>Some contents...</p>
-                <p>Some contents...</p>
-                <p>Some contents...</p>
-                <p>Some contents...</p>
-                <p>Some contents...</p>
-                <p>Some contents...</p>
-                <p>Some contents...</p>
-                <p>Some contents...</p>
-            </SideSheet>
-        </div>
-
-    );
+  const [visible, setVisible] = useState(false);
+  const [placement, setPlacement] = useState('right');
+  const handleCancel = e => {
+    setVisible(false);
+  };
+
+  const onSelect = e => {
+    setPlacement(e.target.value);
+  };
+  return (
+    <div
+      style={{
+        height: 200,
+        overflow: 'hidden',
+        position: 'relative',
+        border: '1px solid #ebedf0',
+        borderRadius: 2,
+        padding: 48,
+        textAlign: 'center',
+        background: '#fafafa',
+      }}
+      className="sidesheet-container"
+    >
+      Render in this
+      <div style={{ marginTop: 16 }}>
+        <Button onClick={() => setVisible(true)}> show sideSheet </Button>
+        <RadioGroup onChange={e => onSelect(e)} value={placement}>
+          <Radio value={'right'}>right</Radio>
+          <Radio value={'left'}>left</Radio>
+          <Radio value={'top'}>top</Radio>
+          <Radio value={'bottom'}>bottom</Radio>
+        </RadioGroup>
+      </div>
+      <SideSheet
+        visible={visible}
+        title="sideSheet"
+        height="100px"
+        placement={'right'}
+        onCancel={handleCancel}
+        placement={placement}
+        mask={false}
+        bodyStyle={{ overflow: 'auto', height: 200 }}
+        getPopupContainer={() => document.querySelector('.sidesheet-container')}
+      >
+        <p>Some contents...</p>
+        <p>Some contents...</p>
+        <p>Some contents...</p>
+        <p>Some contents...</p>
+        <p>Some contents...</p>
+        <p>Some contents...</p>
+        <p>Some contents...</p>
+        <p>Some contents...</p>
+        <p>Some contents...</p>
+        <p>Some contents...</p>
+        <p>Some contents...</p>
+        <p>Some contents...</p>
+        <p>Some contents...</p>
+        <p>Some contents...</p>
+        <p>Some contents...</p>
+        <p>Some contents...</p>
+      </SideSheet>
+    </div>
+  );
 };
 
-stories.add('sidesheet getpopupcontanier and non-blocking', () => <Combox />);
+export const SidesheetGetpopupcontanierAndNonBlocking = () => <Combox />;
+
+SidesheetGetpopupcontanierAndNonBlocking.story = {
+  name: 'sidesheet getpopupcontanier and non-blocking',
+};
 
 const WithFooter = () => {
-    const [visible, setVisible] = useState(false);
-    const handleCancel = e => {
-        setVisible(false);
-    };
-    const show = () => {
-        setVisible(true);
-    }
-
-    return (
-        <div>
-            <Button onClick={() => show()}>Open SideSheet</Button>
-            <SideSheet
-                visible={visible}
-                title='sideSheet'
-                footer={<div>1234</div>}
-                placement={'right'}
-                onCancel={handleCancel}
-            // bodyStyle={{ overflow: 'auto', height: 200 }}
-            >
-                <p>Some contents...</p>
-                <p>Some contents...</p>
-                <p>Some contents...</p>
-                <p>Some contents...</p>
-                <p>Some contents...</p>
-                <p>Some contents...</p>
-            </SideSheet>
-        </div>
-    );
+  const [visible, setVisible] = useState(false);
+  const handleCancel = e => {
+    setVisible(false);
+  };
+  const show = () => {
+    setVisible(true);
+  };
+
+  return (
+    <div>
+      <Button onClick={() => show()}>Open SideSheet</Button>
+      <SideSheet
+        visible={visible}
+        title="sideSheet"
+        footer={<div>1234</div>}
+        placement={'right'}
+        onCancel={handleCancel}
+        // bodyStyle={{ overflow: 'auto', height: 200 }}
+      >
+        <p>Some contents...</p>
+        <p>Some contents...</p>
+        <p>Some contents...</p>
+        <p>Some contents...</p>
+        <p>Some contents...</p>
+        <p>Some contents...</p>
+      </SideSheet>
+    </div>
+  );
 };
 
-stories.add('WithFooter', () => <WithFooter />);
+export const _WithFooter = () => <WithFooter />;
 
+_WithFooter.story = {
+  name: 'WithFooter',
+};
 
 const MaskFalseDemo = () => {
-    const [visible, setVisible] = useState(false);
-    const handleCancel = e => {
-        setVisible(false);
-    };
-    const show = () => {
-        setVisible(true);
-    }
-
-    return (
-        <div>
-            <Button onClick={() => show()}>Open SideSheet</Button>
-            <SideSheet
-                mask={false}
-                width="90%"
-                visible={visible}
-                placement={'right'}
-                onCancel={handleCancel}
-            >
-                <p>Some contents...</p>
-                <p>Some contents...</p>
-                <p>Some contents...</p>
-                <p>Some contents...</p>
-            </SideSheet>
-        </div>
-    );
+  const [visible, setVisible] = useState(false);
+  const handleCancel = e => {
+    setVisible(false);
+  };
+  const show = () => {
+    setVisible(true);
+  };
+
+  return (
+    <div>
+      <Button onClick={() => show()}>Open SideSheet</Button>
+      <SideSheet
+        mask={false}
+        width="90%"
+        visible={visible}
+        placement={'right'}
+        onCancel={handleCancel}
+      >
+        <p>Some contents...</p>
+        <p>Some contents...</p>
+        <p>Some contents...</p>
+        <p>Some contents...</p>
+      </SideSheet>
+    </div>
+  );
 };
 
-stories.add('width percent & mask=false', () => <MaskFalseDemo />);
+export const WidthPercentMaskFalse = () => <MaskFalseDemo />;
+
+WidthPercentMaskFalse.story = {
+  name: 'width percent & mask=false',
+};

+ 67 - 58
packages/semi-ui/skeleton/_story/skeleton.stories.js

@@ -1,5 +1,4 @@
 import React, { useMemo } from 'react';
-import { storiesOf } from '@storybook/react';
 // import { withKnobs, text, boolean } from '@storybook/addon-knobs';
 import withPropsCombinations from 'react-storybook-addon-props-combinations';
 
@@ -8,66 +7,76 @@ import { Table } from '@douyinfe/semi-ui/';
 import Skeleton from '../index';
 import Avatar from '../../avatar';
 
-const stories = storiesOf('Skeleton', module);
+export default {
+  title: 'Skeleton'
+}
 
-// stories.addDecorator(withKnobs);;
+export const _Skeleton = () => (
+  <div>
+    <Skeleton placeholder={<Skeleton.Avatar />} loading={true}>
+      <Avatar>U</Avatar>
+    </Skeleton>
+    <Skeleton placeholder={<Skeleton.Image />} loading={true}>
+      <Avatar>U</Avatar>
+    </Skeleton>
+    <Skeleton placeholder={<Skeleton.Paragraph row={6} />} loading={true}>
+      <Avatar>U</Avatar>
+    </Skeleton>
+    <Skeleton placeholder={<Skeleton.Button />} loading={true}>
+      <Avatar>U</Avatar>
+    </Skeleton>
+    <Skeleton placeholder={<Skeleton.Title />} loading={true}>
+      <Avatar>U</Avatar>
+    </Skeleton>
+  </div>
+);
 
-stories.add('Skeleton', () => (
-    <div>
-        <Skeleton placeholder={<Skeleton.Avatar />} loading={true}>
-            <Avatar>U</Avatar>
-        </Skeleton>
-        <Skeleton placeholder={<Skeleton.Image />} loading={true}>
-            <Avatar>U</Avatar>
-        </Skeleton>
-        <Skeleton placeholder={<Skeleton.Paragraph row={6} />} loading={true}>
-            <Avatar>U</Avatar>
-        </Skeleton>
-        <Skeleton placeholder={<Skeleton.Button />} loading={true}>
-            <Avatar>U</Avatar>
-        </Skeleton>
-        <Skeleton placeholder={<Skeleton.Title />} loading={true}>
-            <Avatar>U</Avatar>
-        </Skeleton>
-    </div>
-));
+export const _Table = () => {
+  const Demo = () => {
+    const phArray = [1, 2, 1, 1, 1, 1, 2, 1];
+    const columns = useMemo(
+      () =>
+        phArray.map((key, idx) => {
+          const item = {};
+          item.title = <Skeleton.Title style={{ width: '0' }} />;
+          item.dataIndex = key;
+          item.key = idx;
+          return item;
+        }),
+      phArray
+    );
+    const dataSource = useMemo(
+      () =>
+        [1, 2, 3, 4, 5].map(key => {
+          const item = {};
+          item.key = key;
+          phArray.forEach(i => {
+            const width = 50 * i;
+            item[i] = <Skeleton.Paragraph style={{ width }} rows={1} />;
+          });
+          return item;
+        }),
+      []
+    );
 
-// avatar, image, paragraph, title, button
+    const placeholder = (
+      <div style={{ position: 'relative' }}>
+        <Table
+          style={{ backgroundColor: 'var(--semi-color-bg-1)' }}
+          columns={columns}
+          dataSource={dataSource}
+          pagination={false}
+        />
+        <div style={{ position: 'absolute', left: 0, right: 0, top: 0, bottom: 0 }} />
+      </div>
+    );
 
-stories.add('table', () => {
-    const Demo = () => {
-        const phArray = [1, 2, 1, 1, 1, 1, 2, 1];
-        const columns = useMemo(() => phArray.map((key, idx) => {
-            const item = {};
-            item.title = <Skeleton.Title style={{ width: '0' }} />;
-            item.dataIndex = key;
-            item.key = idx;
-            return item;
-        }), phArray);
-        const dataSource = useMemo(() => [1, 2, 3, 4, 5].map(key => {
-            const item = {};
-            item.key = key;
-            phArray.forEach(i => {
-                const width = 50 * i;
-                item[i] = <Skeleton.Paragraph style={{ width }} rows={1} />;
-            });
-            return item;
-        }), []);
+    return <Skeleton placeholder={placeholder} loading={true} />;
+  };
 
-        const placeholder = (
-            <div style={{ position: 'relative' }}>
-                <Table
-                    style={{ backgroundColor: 'var(--semi-color-bg-1)' }}
-                    columns={columns}
-                    dataSource={dataSource}
-                    pagination={false}
-                />
-                <div style={{ position: 'absolute', left: 0, right: 0, top: 0, bottom: 0 }} />
-            </div>
-        );
+  return <Demo />;
+};
 
-        return <Skeleton placeholder={placeholder} loading={true} />;
-    };
-
-    return <Demo />;
-});
+_Table.story = {
+  name: 'table',
+};

+ 365 - 246
packages/semi-ui/slider/_story/slider.stories.js

@@ -1,285 +1,404 @@
 import React, { Component } from 'react';
-import { storiesOf } from '@storybook/react';
-// import { withKnobs, text, boolean } from '@storybook/addon-knobs';
-import withPropsCombinations from 'react-storybook-addon-props-combinations';
 import Slider from '../index';
-// import Button from '../../button/index';
 import Input from '../../input/index';
 import { Modal, Button, Form, Row, Col } from '@douyinfe/semi-ui/';
 
-const stories = storiesOf('Slider', module);
-
-// stories.addDecorator(withKnobs);;
+export default {
+  title: 'Slider'
+}
 
 function formatter(value) {
-    return `${value}自定义`;
+  return `${value}自定义`;
 }
 let divStyle = {
-    width: 800,
-    marginLeft: 20,
-    marginTop: 40,
-    paddingBottom: 30
-}
-stories.add('horizontal slider', () => (
-    <div>
-        <div style={divStyle}>
-            <div>default</div>
-            <Slider showBoundary={true} onChange={(value) => { console.log('value改变了' + value) }}></Slider>
-        </div>
-        <div style={divStyle}>
-            <div>min, max</div>
-            <Slider showBoundary={true} min={10} max={50} onChange={(value) => { console.log('value改变了' + value) }}></Slider>
-        </div>
-        <div style={divStyle}>
-            <div>range</div>
-            <Slider
-                defaultValue={[20, 60]}
-                range
-                // step={0.01}
-                onChange={(value) => { console.log('value改变了啊啊啊啊啊啊' + value) }}
-                onAfterChange={(value) => { console.log('value结束于' + value) }}
-            ></Slider>
-        </div>
-        <div style={divStyle}>
-            <div>组合输入框</div>
-            <InputSlider />
-        </div>
-        <div style={divStyle}>
-            <div>格式化tooltip</div>
-            <Slider tipFormatter={formatter} onChange={(value) => { console.log('value改变了' + value) }}></Slider>
-        </div>
-        <div style={divStyle}>
-            <div>tooltip=null</div>
-            <Slider tipFormatter={null} onChange={(value) => { console.log('value改变了' + value) }}></Slider>
-        </div>
-        <div style={divStyle}>
-            <div>tooltipVisible=true始终显示tooltip</div>
-            <Slider tooltipVisible={true} onChange={(value) => { console.log('value改变了' + value) }}></Slider>
-        </div>
-        <div style={divStyle}>
-            <div>step=10</div>
-            <Slider step={10} marks={{ 10: '10', 20: '20', 30: '30', 40: '40', 50: '50' }} defaultValue={[10, 100]} range={true} onChange={(value) => { console.log('value改变了' + value) }}></Slider>
-        </div>
-        <div style={divStyle}>
-            <div>step=0.1</div>
-            <Slider step={0.1} marks={{ 0.1: '0.1', 0.2: '0.2', 0.3: '0.3', 0.4: '0.4', 0.5: '0.5' }} min={0} max={1} defaultValue={[0.1, 0.5]} range={true} onChange={(value) => { console.log('value改变了' + value) }}></Slider>
-        </div>
-        <div style={divStyle}>
-            <div>marks</div>
-            <Slider marks={{ 20: '20c', 40: '40c' }} defaultValue={[0, 100]} range={true} onChange={(value) => { console.log('value改变了' + value) }}></Slider>
-        </div>
-        <div style={divStyle}>
-            <div>inclued</div>
-            <Slider marks={{ 20: '20c', 40: '40c' }} included={false} defaultValue={[0, 100]} range={true} onChange={(value) => { console.log('value改变了' + value) }}></Slider>
-        </div>
+  width: 800,
+  marginLeft: 20,
+  marginTop: 40,
+  paddingBottom: 30,
+};
+
+export const HorizontalSlider = () => (
+  <div>
+    <div style={divStyle}>
+      <div>default</div>
+      <Slider
+        showBoundary={true}
+        onChange={value => {
+          console.log('value改变了' + value);
+        }}
+      ></Slider>
+    </div>
+    <div style={divStyle}>
+      <div>min, max</div>
+      <Slider
+        showBoundary={true}
+        min={10}
+        max={50}
+        onChange={value => {
+          console.log('value改变了' + value);
+        }}
+      ></Slider>
+    </div>
+    <div style={divStyle}>
+      <div>range</div>
+      <Slider
+        defaultValue={[20, 60]}
+        range
+        // step={0.01}
+        onChange={value => {
+          console.log('value改变了啊啊啊啊啊啊' + value);
+        }}
+        onAfterChange={value => {
+          console.log('value结束于' + value);
+        }}
+      ></Slider>
+    </div>
+    <div style={divStyle}>
+      <div>组合输入框</div>
+      <InputSlider />
+    </div>
+    <div style={divStyle}>
+      <div>格式化tooltip</div>
+      <Slider
+        tipFormatter={formatter}
+        onChange={value => {
+          console.log('value改变了' + value);
+        }}
+      ></Slider>
+    </div>
+    <div style={divStyle}>
+      <div>tooltip=null</div>
+      <Slider
+        tipFormatter={null}
+        onChange={value => {
+          console.log('value改变了' + value);
+        }}
+      ></Slider>
+    </div>
+    <div style={divStyle}>
+      <div>tooltipVisible=true始终显示tooltip</div>
+      <Slider
+        tooltipVisible={true}
+        onChange={value => {
+          console.log('value改变了' + value);
+        }}
+      ></Slider>
     </div>
-));
+    <div style={divStyle}>
+      <div>step=10</div>
+      <Slider
+        step={10}
+        marks={{ 10: '10', 20: '20', 30: '30', 40: '40', 50: '50' }}
+        defaultValue={[10, 100]}
+        range={true}
+        onChange={value => {
+          console.log('value改变了' + value);
+        }}
+      ></Slider>
+    </div>
+    <div style={divStyle}>
+      <div>step=0.1</div>
+      <Slider
+        step={0.1}
+        marks={{ 0.1: '0.1', 0.2: '0.2', 0.3: '0.3', 0.4: '0.4', 0.5: '0.5' }}
+        min={0}
+        max={1}
+        defaultValue={[0.1, 0.5]}
+        range={true}
+        onChange={value => {
+          console.log('value改变了' + value);
+        }}
+      ></Slider>
+    </div>
+    <div style={divStyle}>
+      <div>marks</div>
+      <Slider
+        marks={{ 20: '20c', 40: '40c' }}
+        defaultValue={[0, 100]}
+        range={true}
+        onChange={value => {
+          console.log('value改变了' + value);
+        }}
+      ></Slider>
+    </div>
+    <div style={divStyle}>
+      <div>inclued</div>
+      <Slider
+        marks={{ 20: '20c', 40: '40c' }}
+        included={false}
+        defaultValue={[0, 100]}
+        range={true}
+        onChange={value => {
+          console.log('value改变了' + value);
+        }}
+      ></Slider>
+    </div>
+  </div>
+);
+
+HorizontalSlider.story = {
+  name: 'horizontal slider',
+};
 
 class InputSlider extends Component {
-    state = {
-        value: 10
-    }
+  state = {
+    value: 10,
+  };
 
-    getSliderValue = (value) => {
-        this.setState({ value: value / 1 });
-    }
+  getSliderValue = value => {
+    this.setState({ value: value / 1 });
+  };
 
-    render() {
-        const { value } = this.state
-        return (
-            <div style={{ display: 'flex', width: 800 }}>
-                <div style={{ width: 500 }}>
-                    <Slider step={0.1} value={value} onChange={(value) => (this.getSliderValue(value))}></Slider>
-                </div>
-                <Input onChange={(v) => this.getSliderValue(v)} style={{ flex: 1 }} value={value} />
-            </div>
-            // <div>
-            // <div style={{display:'inlineBlock'}}>
-            //     <Slider step={0.1} onChange={(value) => (this.getSliderValue(value))}></Slider>
-            //     <Input  value={value} />
-            // </div>
-            //  </div>
-        );
-    }
+  render() {
+    const { value } = this.state;
+    return (
+      <div style={{ display: 'flex', width: 800 }}>
+        <div style={{ width: 500 }}>
+          <Slider step={0.1} value={value} onChange={value => this.getSliderValue(value)}></Slider>
+        </div>
+        <Input onChange={v => this.getSliderValue(v)} style={{ flex: 1 }} value={value} />
+      </div>
+    );
+  }
 }
 
 let divStyle1 = {
-    height: 400,
-    marginLeft: 20,
-    marginTop: 40,
-    paddingRight: 30,
-    display: 'inline-block'
-}
+  height: 400,
+  marginLeft: 20,
+  marginTop: 40,
+  paddingRight: 30,
+  display: 'inline-block',
+};
 
-stories.add('vertical slider', () => (
-    <div>
-        <div style={divStyle1}>
-            <Slider vertical range defaultValue={[20, 60]}></Slider>
-        </div>
-        {/* <div style={divStyle1}>
-            <Slider vertical onChange={(value) => { }}></Slider>
-        </div>
-        <div style={divStyle1}>
-            <Slider vertical range defaultValue={[20, 60]} onChange={(value) => { console.log('value改变了' + value) }}></Slider>
-        </div>
-        <div style={divStyle1}>
-            <Slider vertical range marks={{ 20: '20c', 40: '40c' }} step={10} defaultValue={[20, 60]} onChange={(value) => { console.log('value改变了' + value) }}></Slider>
-        </div> */}
+export const VerticalSlider = () => (
+  <div>
+    <div style={divStyle1}>
+      <Slider vertical range defaultValue={[20, 60]}></Slider>
     </div>
-));
+  </div>
+);
 
-stories.add('在滚动容器中的vertical slider', () => (
-    <div style={{ height: '300px', overflow: 'scroll' }}>
-        <div style={{ height: '600px', marginTop: '30px' }}>
-            <div style={divStyle1}>
-                <Slider vertical onChange={(value) => { }}></Slider>
-            </div>
-            <div style={divStyle1}>
-                <Slider vertical range defaultValue={[20, 60]} onChange={(value) => { console.log('value改变了' + value) }}></Slider>
-            </div>
-            <div style={divStyle1}>
-                <Slider vertical range marks={{ 20: '20c', 40: '40c' }} step={10} defaultValue={[20, 60]} onChange={(value) => { console.log('value改变了' + value) }}></Slider>
-            </div>
-        </div>
+VerticalSlider.story = {
+  name: 'vertical slider',
+};
+
+export const VerticalSliderInScrollContainer = () => (
+  <div style={{ height: '300px', overflow: 'scroll' }}>
+    <div style={{ height: '600px', marginTop: '30px' }}>
+      <div style={divStyle1}>
+        <Slider vertical onChange={value => {}}></Slider>
+      </div>
+      <div style={divStyle1}>
+        <Slider
+          vertical
+          range
+          defaultValue={[20, 60]}
+          onChange={value => {
+            console.log('value改变了' + value);
+          }}
+        ></Slider>
+      </div>
+      <div style={divStyle1}>
+        <Slider
+          vertical
+          range
+          marks={{ 20: '20c', 40: '40c' }}
+          step={10}
+          defaultValue={[20, 60]}
+          onChange={value => {
+            console.log('value改变了' + value);
+          }}
+        ></Slider>
+      </div>
     </div>
-));
+  </div>
+);
 
-stories.add('在滚动容器中的slider', () => (
-    <div style={{ width: '300px', overflow: 'scroll' }}>
-        <div style={{ width: '500px', marginTop: '10px' }}>
-            <div style={divStyle}>
-                <Slider onChange={(value) => { }}></Slider>
-            </div>
-            <div style={divStyle}>
-                <Slider range defaultValue={[20, 60]} onChange={(value) => { console.log('value改变了' + value) }}></Slider>
-            </div>
-            <div style={divStyle}>
-                <Slider range marks={{ 20: '20c', 40: '40c' }} step={10} defaultValue={[20, 60]} onChange={(value) => { console.log('value改变了' + value) }}></Slider>
-            </div>
-        </div>
+VerticalSliderInScrollContainer.story = {
+  name: '在滚动容器中的vertical slider',
+};
+
+export const SliderInScrollContainer = () => (
+  <div style={{ width: '300px', overflow: 'scroll' }}>
+    <div style={{ width: '500px', marginTop: '10px' }}>
+      <div style={divStyle}>
+        <Slider onChange={value => {}}></Slider>
+      </div>
+      <div style={divStyle}>
+        <Slider
+          range
+          defaultValue={[20, 60]}
+          onChange={value => {
+            console.log('value改变了' + value);
+          }}
+        ></Slider>
+      </div>
+      <div style={divStyle}>
+        <Slider
+          range
+          marks={{ 20: '20c', 40: '40c' }}
+          step={10}
+          defaultValue={[20, 60]}
+          onChange={value => {
+            console.log('value改变了' + value);
+          }}
+        ></Slider>
+      </div>
     </div>
-));
+  </div>
+);
 
+SliderInScrollContainer.story = {
+  name: '在滚动容器中的slider'
+}
 
-class ControllSlider extends Component {
-    state = {
-        value: 50,
-        rangeValue: undefined
-    }
-    changeValue = () => {
-        this.setState({ value: this.state.value + 10 });
-    }
-    changeRangeValue = rangeValue => {
-        console.log('rangeValue' + rangeValue);
-        this.setState({ rangeValue: rangeValue });
-    }
-    render() {
-        const { value, rangeValue } = this.state;
-        return (
-            <div>
-                <Button onClick={() => this.changeValue()}>点击改变value</Button>
-                <div style={{ width: 800, marginLeft: 20, marginTop: 40 }}>
-                    <Slider value={value} onChange={(value) => { console.log('value改变了' + value) }}></Slider>
-                </div>
-                <div style={{ width: 800, marginLeft: 20, marginTop: 40 }}>
-                    <Slider value={rangeValue} onChange={(rangeValue) => this.changeRangeValue(rangeValue)} range></Slider>
-                </div>
-            </div>
-        );
-    }
+class ControlledSlider extends Component {
+  state = {
+    value: 50,
+    rangeValue: undefined,
+  };
+  changeValue = () => {
+    this.setState({ value: this.state.value + 10 });
+  };
+  changeRangeValue = rangeValue => {
+    console.log('rangeValue' + rangeValue);
+    this.setState({ rangeValue: rangeValue });
+  };
+  render() {
+    const { value, rangeValue } = this.state;
+    return (
+      <div>
+        <Button onClick={() => this.changeValue()}>点击改变value</Button>
+        <div style={{ width: 800, marginLeft: 20, marginTop: 40 }}>
+          <Slider
+            value={value}
+            onChange={value => {
+              console.log('value改变了' + value);
+            }}
+          ></Slider>
+        </div>
+        <div style={{ width: 800, marginLeft: 20, marginTop: 40 }}>
+          <Slider
+            value={rangeValue}
+            onChange={rangeValue => this.changeRangeValue(rangeValue)}
+            range
+          ></Slider>
+        </div>
+      </div>
+    );
+  }
 }
 
-stories.add('受控slider', () => <ControllSlider />);
+export const ControlledSliderDemo = () => <ControlledSlider />;
+ControlledSliderDemo.story = {
+  name: '受控slider'
+}
 
 class DisableSlider extends Component {
-    state = {
-        disabled: false
-    }
-    changeValue = () => {
-        this.setState({ disabled: !this.state.disabled });
-    }
-    render() {
-        const { disabled } = this.state
-        return (
-            <div>
-                <Button onClick={() => this.changeValue()}>toggle disable slider</Button>
-                <div style={{ width: 800, marginLeft: 20, marginTop: 40 }}>
-                    <Slider disabled={disabled} defaultValue={10} onChange={(value) => { console.log('value改变了' + value) }}></Slider>
-                </div>
-            </div>
-        );
-    }
+  state = {
+    disabled: false,
+  };
+  changeValue = () => {
+    this.setState({ disabled: !this.state.disabled });
+  };
+  render() {
+    const { disabled } = this.state;
+    return (
+      <div>
+        <Button onClick={() => this.changeValue()}>toggle disable slider</Button>
+        <div style={{ width: 800, marginLeft: 20, marginTop: 40 }}>
+          <Slider
+            disabled={disabled}
+            defaultValue={10}
+            onChange={value => {
+              console.log('value改变了' + value);
+            }}
+          ></Slider>
+        </div>
+      </div>
+    );
+  }
 }
 
-stories.add('disable slider', () => <DisableSlider />);
+export const _DisableSlider = () => <DisableSlider />;
 
+_DisableSlider.story = {
+  name: 'disable slider',
+};
 
 class TestDemo extends React.Component {
-    constructor() {
-        super();
-        this.state = {
-            visible: false
-        };
-        this.showDialog = this.showDialog.bind(this);
-        this.getFormApi = this.getFormApi.bind(this);
-        this.handleOk = this.handleOk.bind(this);
-        this.handleCancel = this.handleCancel.bind(this);
-    }
-    getFormApi(formApi) { this.formApi = formApi }
-    showDialog() {
-        this.setState({
-            visible: true
-        });
-    }
-    handleOk(e) {
-        this.setState({
-            visible: false
-        });
-    }
-    handleCancel(e) {
-        this.setState({
-            visible: false,
-        });
-    }
-    render() {
-        const { Slider, Switch } = Form;
-        return (
-            <>
-                <Button onClick={this.showDialog}>打开弹窗</Button>
-                <Modal
-                    title="基本对话框"
-                    visible={this.state.visible}
-                    onOk={this.handleOk}
-                    onCancel={this.handleCancel}
-                >
-                    <Form
-                        style={{ padding: 10, width: '100%' }}
-                        onValueChange={(v) => console.log(v)}
-                    >
-                        <Row>
-                            <Col span={12}>
-                                <Slider field="range" range initValue={[10, 100]} style={{ width: '90%' }} />
-                            </Col>
-                            <Col span={12}>
-                                <Switch field='switch' />
-                            </Col>
-                        </Row>
-                    </Form>
-                </Modal>
-            </>
-        );
-    }
+  constructor() {
+    super();
+    this.state = {
+      visible: false,
+    };
+    this.showDialog = this.showDialog.bind(this);
+    this.getFormApi = this.getFormApi.bind(this);
+    this.handleOk = this.handleOk.bind(this);
+    this.handleCancel = this.handleCancel.bind(this);
+  }
+  getFormApi(formApi) {
+    this.formApi = formApi;
+  }
+  showDialog() {
+    this.setState({
+      visible: true,
+    });
+  }
+  handleOk(e) {
+    this.setState({
+      visible: false,
+    });
+  }
+  handleCancel(e) {
+    this.setState({
+      visible: false,
+    });
+  }
+  render() {
+    const { Slider, Switch } = Form;
+    return (
+      <>
+        <Button onClick={this.showDialog}>打开弹窗</Button>
+        <Modal
+          title="基本对话框"
+          visible={this.state.visible}
+          onOk={this.handleOk}
+          onCancel={this.handleCancel}
+        >
+          <Form style={{ padding: 10, width: '100%' }} onValueChange={v => console.log(v)}>
+            <Row>
+              <Col span={12}>
+                <Slider field="range" range initValue={[10, 100]} style={{ width: '90%' }} />
+              </Col>
+              <Col span={12}>
+                <Switch field="switch" />
+              </Col>
+            </Row>
+          </Form>
+        </Modal>
+      </>
+    );
+  }
 }
 
-stories.add('slider in modal', () => <TestDemo />);
+export const SliderInModal = () => <TestDemo />;
 
-stories.add('range min slider', () => (
-    <Slider
-        defaultValue={[20, 60]}
-        range
-        // step={0.01}
-        min={10}
+SliderInModal.story = {
+  name: 'slider in modal',
+};
+
+export const RangeMinSlider = () => (
+  <Slider
+    defaultValue={[20, 60]}
+    range
+    // step={0.01}
+    min={10}
     // onChange={(value) => { console.log('value改变了啊啊啊啊啊啊' + value) }}
     // onAfterChange={(value) => { console.log('value结束于' + value) }}
-    />
-));
+  />
+);
+
+RangeMinSlider.story = {
+  name: 'range min slider',
+};

+ 242 - 214
packages/semi-ui/space/_story/space.stories.js

@@ -1,226 +1,254 @@
 import React from 'react';
-import { storiesOf } from '@storybook/react';
 import { Button, Tag } from '@douyinfe/semi-ui/';
 import Space from '../index';
 
-const stories = storiesOf('Space', module);
+export default {
+  title: 'Space'
+}
 
 const divStyle = {
-    width: 100,
-    height: 100,
-    backgroundColor:'lightblue',
-    display: 'flex',
-    alignItems: 'center'
-}
-stories.add('Space default', () => (
-    <>
-        <Space align='baseline'>
-            <Button onClick={()=>{alert('button')}}>按钮</Button>
-            <Button>按钮</Button>
-            <Tag> default tag </Tag>
-            <div style={divStyle}>div</div>
-        </Space>
-    </>
-));
+  width: 100,
+  height: 100,
+  backgroundColor: 'lightblue',
+  display: 'flex',
+  alignItems: 'center',
+};
+
+export const SpaceDefault = () => (
+  <>
+    <Space align="baseline">
+      <Button
+        onClick={() => {
+          alert('button');
+        }}
+      >
+        按钮
+      </Button>
+      <Button>按钮</Button>
+      <Tag> default tag </Tag>
+      <div style={divStyle}>div</div>
+    </Space>
+  </>
+);
+
+SpaceDefault.story = {
+  name: 'Space default',
+};
+
+export const SpaceAlign = () => (
+  <>
+    <Space align="center">
+      <span>horizontal:align-center</span>
+      <Button>按钮</Button>
+      <Button>按钮</Button>
+      <Tag> default tag </Tag>
+      <div style={divStyle}>div</div>
+    </Space>
+    <br />
+    <Space align="start">
+      <span>horizontal:align-start</span>
+      <Button>按钮</Button>
+      <Button>按钮</Button>
+      <Tag> default tag </Tag>
+      <div style={divStyle}>div</div>
+    </Space>
+    <br />
+    <Space align="end">
+      <span>horizontal:align-end</span>
+      <Button>按钮</Button>
+      <Button>按钮</Button>
+      <Tag> default tag </Tag>
+      <div style={divStyle}>div</div>
+    </Space>
+    <br />
+    <Space align="baseline">
+      <span>horizontal:align-baseline</span>
+      <Button>按钮</Button>
+      <Button>按钮</Button>
+      <Tag> default tag </Tag>
+      <div style={divStyle}>div</div>
+    </Space>
+    <hr />
+    <br />
+    <Space vertical align="center">
+      <span>vertical:align-center</span>
+      <Button>按钮</Button>
+      <Button>按钮</Button>
+      <Tag> default tag </Tag>
+      <div style={divStyle}>div</div>
+    </Space>
+    <br />
+    <Space vertical align="start">
+      <span>vertical:align-start</span>
+      <Button>按钮</Button>
+      <Button>按钮</Button>
+      <Tag> default tag </Tag>
+      <div style={divStyle}>div</div>
+    </Space>
+    <br />
+    <Space vertical align="end">
+      <span>vertical:align-end</span>
+      <Button>按钮</Button>
+      <Button>按钮</Button>
+      <Tag> default tag </Tag>
+      <div style={divStyle}>div</div>
+    </Space>
+    <br />
+    <Space vertical align="baseline">
+      <span>vertical:align-baseline</span>
+      <Button>按钮</Button>
+      <Button>按钮</Button>
+      <Tag> default tag </Tag>
+      <div style={divStyle}>div</div>
+    </Space>
+  </>
+);
+
+SpaceAlign.story = {
+  name: 'Space align',
+};
 
-stories.add('Space align', () => (
-    <>
-        <Space align='center'>
-            <span>horizontal:align-center</span>
-            <Button>按钮</Button>
-            <Button>按钮</Button>
-            <Tag> default tag </Tag>
-            <div style={divStyle}>div</div>
-        </Space>
-        <br />
-        <Space align='start'>
-            <span>horizontal:align-start</span>
-            <Button>按钮</Button>
-            <Button>按钮</Button>
-            <Tag> default tag </Tag>
-            <div style={divStyle}>div</div>
-        </Space>
-        <br />
-        <Space align='end'>
-            <span>horizontal:align-end</span>
-            <Button>按钮</Button>
-            <Button>按钮</Button>
-            <Tag> default tag </Tag>
-            <div style={divStyle}>div</div>
-        </Space>
-        <br />
-        <Space align='baseline'>
-            <span>horizontal:align-baseline</span>
-            <Button>按钮</Button>
-            <Button>按钮</Button>
-            <Tag> default tag </Tag>
-            <div style={divStyle}>div</div>
-        </Space>
-        <hr />
-        <br />
-        <Space vertical align='center'>
-            <span>vertical:align-center</span>
-            <Button>按钮</Button>
-            <Button>按钮</Button>
-            <Tag> default tag </Tag>
-            <div style={divStyle}>div</div>
-        </Space>
-        <br />
-        <Space vertical align='start'>
-            <span>vertical:align-start</span>
-            <Button>按钮</Button>
-            <Button>按钮</Button>
-            <Tag> default tag </Tag>
-            <div style={divStyle}>div</div>
-        </Space>
-        <br />
-        <Space vertical align='end'>
-            <span>vertical:align-end</span>
-            <Button>按钮</Button>
-            <Button>按钮</Button>
-            <Tag> default tag </Tag>
-            <div style={divStyle}>div</div>
-        </Space>
-        <br />
-        <Space vertical align='baseline'>
-            <span>vertical:align-baseline</span>
-            <Button>按钮</Button>
-            <Button>按钮</Button>
-            <Tag> default tag </Tag>
-            <div style={divStyle}>div</div>
-        </Space>
-    </>
-));
+export const SpaceVertical = () => (
+  <>
+    <Space direction="horizontal">
+      <Button>主要按钮</Button>
+      <Button type="secondary">次要按钮</Button>
+      <Button type="tertiary">第三按钮</Button>
+      <Button type="warning">警告按钮</Button>
+      <Button type="danger">危险按钮</Button>
+    </Space>
+    <br />
+    <Space vertical>
+      <Button>主要按钮</Button>
+      <Button type="secondary">次要按钮</Button>
+      <Button type="tertiary">第三按钮</Button>
+      <Button type="warning">警告按钮</Button>
+      <Button type="danger">危险按钮</Button>
+    </Space>
+  </>
+);
 
+SpaceVertical.story = {
+  name: 'Space vertical',
+};
 
-stories.add('Space vertical', () => (
-    <>
-        <Space direction='horizontal'>
-            <Button>主要按钮</Button>
-            <Button type="secondary">次要按钮</Button>
-            <Button type="tertiary">第三按钮</Button>
-            <Button type="warning">警告按钮</Button>
-            <Button type="danger">危险按钮</Button>
-        </Space>
-        <br />
-        <Space vertical>
-            <Button>主要按钮</Button>
-            <Button type="secondary">次要按钮</Button>
-            <Button type="tertiary">第三按钮</Button>
-            <Button type="warning">警告按钮</Button>
-            <Button type="danger">危险按钮</Button>
-        </Space>
-    </>
-));
+export const SpaceSpacing = () => (
+  <>
+    <Space spacing="loose">
+      <span>spacing-loose</span>
+      <Button>主要按钮</Button>
+      <Button type="secondary">次要按钮</Button>
+      <Button type="tertiary">第三按钮</Button>
+      <Button type="warning">警告按钮</Button>
+      <Button type="danger">危险按钮</Button>
+    </Space>
+    <br />
+    <Space spacing="medium">
+      <span>spacing-medium</span>
+      <Button>主要按钮</Button>
+      <Button type="secondary">次要按钮</Button>
+      <Button type="tertiary">第三按钮</Button>
+      <Button type="warning">警告按钮</Button>
+      <Button type="danger">危险按钮</Button>
+    </Space>
+    <br />
+    <Space spacing="tight">
+      <span>spacing-tight</span>
+      <Button>主要按钮</Button>
+      <Button type="secondary">次要按钮</Button>
+      <Button type="tertiary">第三按钮</Button>
+      <Button type="warning">警告按钮</Button>
+      <Button type="danger">危险按钮</Button>
+    </Space>
+    <br />
+    <Space spacing={30}>
+      <span>spacing-number-30</span>
+      <Button>主要按钮</Button>
+      <Button type="secondary">次要按钮</Button>
+      <Button type="tertiary">第三按钮</Button>
+      <Button type="warning">警告按钮</Button>
+      <Button type="danger">危险按钮</Button>
+    </Space>
+    <br />
+    <Space spacing={[20, 20]}>
+      <span>spacing-array-[20,20]</span>
+      <Button>主要按钮</Button>
+      <Button type="secondary">次要按钮</Button>
+      <Button type="tertiary">第三按钮</Button>
+      <Button type="warning">警告按钮</Button>
+      <Button type="danger">危险按钮</Button>
+    </Space>
+    <br />
+    <Space spacing={['medium', 'loose']}>
+      <span>spacing-array-['medium','loose']</span>
+      <Button>主要按钮</Button>
+      <Button type="secondary">次要按钮</Button>
+      <Button type="tertiary">第三按钮</Button>
+      <Button type="warning">警告按钮</Button>
+      <Button type="danger">危险按钮</Button>
+    </Space>
+    <br />
+    <Space spacing={['medium', 20]}>
+      <span>spacing-array-['medium',20]</span>
+      <Button>主要按钮</Button>
+      <Button type="secondary">次要按钮</Button>
+      <Button type="tertiary">第三按钮</Button>
+      <Button type="warning">警告按钮</Button>
+      <Button type="danger">危险按钮</Button>
+    </Space>
+    <br />
+    <Space wrap spacing="loose">
+      <span>spacing-loose,wrap=true</span>
+      <Button>主要按钮</Button>
+      <Button type="secondary">次要按钮</Button>
+      <Button type="tertiary">第三按钮</Button>
+      <Button type="warning">警告按钮</Button>
+      <Button type="danger">危险按钮</Button>
+    </Space>
+    <br />
+    <Space wrap spacing="medium">
+      <span>spacing-medium,wrap=true</span>
+      <Button>主要按钮</Button>
+      <Button type="secondary">次要按钮</Button>
+      <Button type="tertiary">第三按钮</Button>
+      <Button type="warning">警告按钮</Button>
+      <Button type="danger">危险按钮</Button>
+    </Space>
+    <br />
+    <Space wrap spacing="tight">
+      <span>spacing-tight,wrap=true</span>
+      <Button>主要按钮</Button>
+      <Button type="secondary">次要按钮</Button>
+      <Button type="tertiary">第三按钮</Button>
+      <Button type="warning">警告按钮</Button>
+      <Button type="danger">危险按钮</Button>
+    </Space>
+    <br />
+  </>
+);
 
-stories.add('Space spacing', () => (
-    <>
-        <Space spacing='loose'>
-            <span>spacing-loose</span>
-            <Button>主要按钮</Button>
-            <Button type="secondary">次要按钮</Button>
-            <Button type="tertiary">第三按钮</Button>
-            <Button type="warning">警告按钮</Button>
-            <Button type="danger">危险按钮</Button>
-        </Space>
-        <br />
-        <Space spacing='medium'>
-            <span>spacing-medium</span>
-            <Button>主要按钮</Button>
-            <Button type="secondary">次要按钮</Button>
-            <Button type="tertiary">第三按钮</Button>
-            <Button type="warning">警告按钮</Button>
-            <Button type="danger">危险按钮</Button>
-        </Space>
-        <br />
-        <Space spacing='tight'>
-            <span>spacing-tight</span>
-            <Button>主要按钮</Button>
-            <Button type="secondary">次要按钮</Button>
-            <Button type="tertiary">第三按钮</Button>
-            <Button type="warning">警告按钮</Button>
-            <Button type="danger">危险按钮</Button>
-        </Space>
-        <br />
-        <Space spacing={30}>
-            <span>spacing-number-30</span>
-            <Button>主要按钮</Button>
-            <Button type="secondary">次要按钮</Button>
-            <Button type="tertiary">第三按钮</Button>
-            <Button type="warning">警告按钮</Button>
-            <Button type="danger">危险按钮</Button>
-        </Space>
-        <br />
-        <Space spacing={[20, 20]}>
-            <span>spacing-array-[20,20]</span>
-            <Button>主要按钮</Button>
-            <Button type="secondary">次要按钮</Button>
-            <Button type="tertiary">第三按钮</Button>
-            <Button type="warning">警告按钮</Button>
-            <Button type="danger">危险按钮</Button>
-        </Space>
-        <br />
-        <Space spacing={['medium', 'loose']}>
-            <span>spacing-array-['medium','loose']</span>
-            <Button>主要按钮</Button>
-            <Button type="secondary">次要按钮</Button>
-            <Button type="tertiary">第三按钮</Button>
-            <Button type="warning">警告按钮</Button>
-            <Button type="danger">危险按钮</Button>
-        </Space>
-        <br />
-        <Space spacing={['medium', 20]}>
-            <span>spacing-array-['medium',20]</span>
-            <Button>主要按钮</Button>
-            <Button type="secondary">次要按钮</Button>
-            <Button type="tertiary">第三按钮</Button>
-            <Button type="warning">警告按钮</Button>
-            <Button type="danger">危险按钮</Button>
-        </Space>
-        <br />
-        <Space wrap spacing='loose'>
-            <span>spacing-loose,wrap=true</span>
-            <Button>主要按钮</Button>
-            <Button type="secondary">次要按钮</Button>
-            <Button type="tertiary">第三按钮</Button>
-            <Button type="warning">警告按钮</Button>
-            <Button type="danger">危险按钮</Button>
-        </Space>
-        <br />
-        <Space wrap spacing='medium'>
-            <span>spacing-medium,wrap=true</span>
-            <Button>主要按钮</Button>
-            <Button type="secondary">次要按钮</Button>
-            <Button type="tertiary">第三按钮</Button>
-            <Button type="warning">警告按钮</Button>
-            <Button type="danger">危险按钮</Button>
-        </Space>
-        <br />
-        <Space wrap spacing='tight'>
-            <span>spacing-tight,wrap=true</span>
-            <Button>主要按钮</Button>
-            <Button type="secondary">次要按钮</Button>
-            <Button type="tertiary">第三按钮</Button>
-            <Button type="warning">警告按钮</Button>
-            <Button type="danger">危险按钮</Button>
-        </Space>
-        <br />
-    </>
-));
-stories.add('Space wrap', () => (
-    <>
-        <Space wrap={false}>
-            {new Array(30).fill(null).map((item, idex) => (
-                <Button key={idex}>按钮</Button>
-            ))}
-        </Space>
-        <br />
-        <Space wrap={true}>
-            {new Array(30).fill(null).map((item, idex) => (
-                <Button theme='solid' type='secondary' key={idex}>按钮</Button>
-            ))}
-        </Space>
-    </>
-));
+SpaceSpacing.story = {
+  name: 'Space spacing',
+};
 
+export const SpaceWrap = () => (
+  <>
+    <Space wrap={false}>
+      {new Array(30).fill(null).map((item, idex) => (
+        <Button key={idex}>按钮</Button>
+      ))}
+    </Space>
+    <br />
+    <Space wrap={true}>
+      {new Array(30).fill(null).map((item, idex) => (
+        <Button theme="solid" type="secondary" key={idex}>
+          按钮
+        </Button>
+      ))}
+    </Space>
+  </>
+);
 
+SpaceWrap.story = {
+  name: 'Space wrap',
+};

+ 76 - 52
packages/semi-ui/spin/_story/spin.stories.js

@@ -1,68 +1,92 @@
 import React, { useState } from 'react';
-import { storiesOf } from '@storybook/react';
-// import { withKnobs, text, boolean } from '@storybook/addon-knobs';
 import Button from '../../button/index';
 import Spin from '../index';
 
-const stories = storiesOf('Spin', module);
-
-// stories.addDecorator(withKnobs);;
+export default {
+  title: 'Spin'
+}
 
 const Example1 = () => (
-    <div style={{marginLeft: 30}}>
-        <div style={{ marginTop: 20 }}>size:small</div>
-        <Spin size="small" />
-        <div style={{ marginTop: 20 }}>size:middle</div>
-        <Spin size="middle" />
-        <div style={{ marginTop: 20 }}>size:large</div>
-        <Spin size="large" />
-    </div>
+  <div style={{ marginLeft: 30 }}>
+    <div style={{ marginTop: 20 }}>size:small</div>
+    <Spin size="small" />
+    <div style={{ marginTop: 20 }}>size:middle</div>
+    <Spin size="middle" />
+    <div style={{ marginTop: 20 }}>size:large</div>
+    <Spin size="large" />
+  </div>
 );
 
-stories.add('spin default', () => <Example1 />);
+export const SpinDefault = () => <Example1 />;
 
-const Example2 = () => {
-    const [visible, setVisible] = useState(true);
-    return (
-        <div>
-            <Spin spinning={visible} tip='loading'>
-                <div style={{ 'background-color': '#e6f7ff', 'border': '1px solid #91d5ff' }}>
-                    <p>yoyoyoyoyo</p>
-                    <p>yoyoyoyoyo</p>
-                    <p>yoyoyoyoyo</p>
-                </div>
-            </Spin>
-            <div style={{marginTop:30}}>
-                    <Button onClick={()=>{setVisible(!visible)}} style={{ marginRight:20 }}>受控</Button>
-            </div>   
-        </div>        
-    )
+SpinDefault.story = {
+  name: 'spin default',
+};
 
-}
+const Example2 = () => {
+  const [visible, setVisible] = useState(true);
+  return (
+    <div>
+      <Spin spinning={visible} tip="loading">
+        <div style={{ 'background-color': '#e6f7ff', border: '1px solid #91d5ff' }}>
+          <p>yoyoyoyoyo</p>
+          <p>yoyoyoyoyo</p>
+          <p>yoyoyoyoyo</p>
+        </div>
+      </Spin>
+      <div style={{ marginTop: 30 }}>
+        <Button
+          onClick={() => {
+            setVisible(!visible);
+          }}
+          style={{ marginRight: 20 }}
+        >
+          受控
+        </Button>
+      </div>
+    </div>
+  );
+};
 
-stories.add('spin has text', () => <Example2 />);
+export const SpinHasText = () => <Example2 />;
 
+SpinHasText.story = {
+  name: 'spin has text',
+};
 
 const Example3 = () => {
-    const [visible1, setVisible1] = useState(false);
-    const [visible2, setVisible2] = useState(false);
-    return (
-        <div style={{marginLeft:30}}>
-            <div style={{marginTop:30}}>
-                <Button onClick={()=>{setVisible1(!visible1)}} style={{ marginRight:20 }}>延迟显示spin</Button>
-                <Spin delay={1000} spinning={visible1}>
-                </Spin>
-            </div> 
-            <div style={{marginTop:30}}>
-                    <Button onClick={()=>{setVisible2(!visible2)}} style={{ marginRight:20 }}>受控显示spin</Button>
-                    <Spin spinning={visible2}>
-                    </Spin>
-            </div>            
-        </div>
-       
-    )
-
-}
+  const [visible1, setVisible1] = useState(false);
+  const [visible2, setVisible2] = useState(false);
+  return (
+    <div style={{ marginLeft: 30 }}>
+      <div style={{ marginTop: 30 }}>
+        <Button
+          onClick={() => {
+            setVisible1(!visible1);
+          }}
+          style={{ marginRight: 20 }}
+        >
+          延迟显示spin
+        </Button>
+        <Spin delay={1000} spinning={visible1}></Spin>
+      </div>
+      <div style={{ marginTop: 30 }}>
+        <Button
+          onClick={() => {
+            setVisible2(!visible2);
+          }}
+          style={{ marginRight: 20 }}
+        >
+          受控显示spin
+        </Button>
+        <Spin spinning={visible2}></Spin>
+      </div>
+    </div>
+  );
+};
 
+export const SpinHasDelay = () => <Example3 />;
 
-stories.add('spin has delay', () => <Example3 />);
+SpinHasDelay.story = {
+  name: 'spin has delay',
+};

+ 258 - 214
packages/semi-ui/steps/_story/steps.stories.js

@@ -1,5 +1,4 @@
 import React, { useState } from 'react';
-import { storiesOf } from '@storybook/react'; // import { withKnobs, text, boolean } from '@storybook/addon-knobs';
 
 import { Form } from '../../form';
 import Radio from '../../radio';
@@ -9,254 +8,299 @@ import Icon from '../../icons';
 import Button from '../../button';
 import { IconTriangleDown, IconClear, IconTick, IconClose, IconBell } from '@douyinfe/semi-icons';
 
-const stories = storiesOf('Steps', module);
+export default {
+  title: 'Steps'
+}
 const sizes = ['default', 'small'];
 
 const AllSteps = () => {
-    const [stepProps, setProps] = useState({
-        type: 'basic',
-        size: 'small',
-        current: 0,
-        hasLine: true,
-        direction: 'horizontal',
-        initial: 0,
-        status: 'finish',
-    });
-    return (
-        <>
-            <Form layout="vertical" labelPosition="left" onValueChange={v => setProps({ ...v })} initValues={stepProps}>
-                <Form.RadioGroup field="type">
-                    <Radio value="fill">fill</Radio>
-                    <Radio value="basic">basic</Radio>
-                    <Radio value="nav">nav</Radio>
-                </Form.RadioGroup>
-                <Form.RadioGroup field="size">
-                    <Radio value="small">small</Radio>
-                    <Radio value="default">default</Radio>
-                </Form.RadioGroup>
-                <Form.RadioGroup field="hasLine">
-                    <Radio value={true}>true</Radio>
-                    <Radio value={false}>false</Radio>
-                </Form.RadioGroup>
-                <Form.InputNumber field="current"></Form.InputNumber>
-                <Form.RadioGroup field="direction">
-                    <Radio value="horizontal">horizontal</Radio>
-                    <Radio value="vertical">vertical</Radio>
-                </Form.RadioGroup>
-                <Form.InputNumber field="initial"></Form.InputNumber>
-                <Form.RadioGroup field="status">
-                    <Radio value="wait">wait</Radio>
-                    <Radio value="process">process</Radio>
-                    <Radio value="finish">finish</Radio>
-                    <Radio value="error">error</Radio>
-                    <Radio value="warning">warning</Radio>
-                </Form.RadioGroup>
-            </Form>
-            <Steps type="basic" {...stepProps}>
-                <Step
-                    title="Step.1"
-                    icon={<IconBell />}
-                    description="This is a long descriptionThis is a long descriptionThis is a long descriptionThis is a long descriptionThis is a long descriptionThis is a long description"
-                ></Step>
-                <Step title="Step.2" description="This is some description"></Step>
-                <Step title="Step.3"></Step>
-                <Step title="Step.4" description="This is some description"></Step>
-            </Steps>
-        </>
-    );
+  const [stepProps, setProps] = useState({
+    type: 'basic',
+    size: 'small',
+    current: 0,
+    hasLine: true,
+    direction: 'horizontal',
+    initial: 0,
+    status: 'finish',
+  });
+  return (
+    <>
+      <Form
+        layout="vertical"
+        labelPosition="left"
+        onValueChange={v => setProps({ ...v })}
+        initValues={stepProps}
+      >
+        <Form.RadioGroup field="type">
+          <Radio value="fill">fill</Radio>
+          <Radio value="basic">basic</Radio>
+          <Radio value="nav">nav</Radio>
+        </Form.RadioGroup>
+        <Form.RadioGroup field="size">
+          <Radio value="small">small</Radio>
+          <Radio value="default">default</Radio>
+        </Form.RadioGroup>
+        <Form.RadioGroup field="hasLine">
+          <Radio value={true}>true</Radio>
+          <Radio value={false}>false</Radio>
+        </Form.RadioGroup>
+        <Form.InputNumber field="current"></Form.InputNumber>
+        <Form.RadioGroup field="direction">
+          <Radio value="horizontal">horizontal</Radio>
+          <Radio value="vertical">vertical</Radio>
+        </Form.RadioGroup>
+        <Form.InputNumber field="initial"></Form.InputNumber>
+        <Form.RadioGroup field="status">
+          <Radio value="wait">wait</Radio>
+          <Radio value="process">process</Radio>
+          <Radio value="finish">finish</Radio>
+          <Radio value="error">error</Radio>
+          <Radio value="warning">warning</Radio>
+        </Form.RadioGroup>
+      </Form>
+      <Steps type="basic" {...stepProps}>
+        <Step
+          title="Step.1"
+          icon={<IconBell />}
+          description="This is a long descriptionThis is a long descriptionThis is a long descriptionThis is a long descriptionThis is a long descriptionThis is a long description"
+        ></Step>
+        <Step title="Step.2" description="This is some description"></Step>
+        <Step title="Step.3"></Step>
+        <Step title="Step.4" description="This is some description"></Step>
+      </Steps>
+    </>
+  );
 };
 
-stories.add('all steps', () => <AllSteps></AllSteps>);
+export const _AllSteps = () => <AllSteps></AllSteps>;
+
+_AllSteps.story = {
+  name: 'all steps',
+};
 
 const FillStep = () => {
-    return sizes.map(s => (
-        <Steps key={s} size={s} current={1}>
-            <Step title="中文" description="This is a description." />
-            <Step title="In Progress" description="This is a description." />
-            <Step title="Waiting" description="This is a description." />
-        </Steps>
-    ));
+  return sizes.map(s => (
+    <Steps key={s} size={s} current={1}>
+      <Step title="中文" description="This is a description." />
+      <Step title="In Progress" description="This is a description." />
+      <Step title="Waiting" description="This is a description." />
+    </Steps>
+  ));
 };
 
-stories.add('steps default fill', () => <FillStep />);
+export const StepsDefaultFill = () => <FillStep />;
+
+StepsDefaultFill.story = {
+  name: 'steps default fill',
+};
 
 const BasicStep = () => {
-    return sizes.map(s => (
-        <Steps key={s} size={s} type="basic" current={1}>
-            <Step title="Step.1" description="This is a description.This is a description." />
-            <Step title="Step.2" description="This is a description.This is a description." />
-            <Step title="Step.3" description="This is a description.This is a description." />
-        </Steps>
-    ));
+  return sizes.map(s => (
+    <Steps key={s} size={s} type="basic" current={1}>
+      <Step title="Step.1" description="This is a description.This is a description." />
+      <Step title="Step.2" description="This is a description.This is a description." />
+      <Step title="Step.3" description="This is a description.This is a description." />
+    </Steps>
+  ));
+};
+
+export const StepsBasic = () => <BasicStep />;
+
+StepsBasic.story = {
+  name: 'steps basic',
+};
+
+export const StepsWithIcon = () => {
+  return (
+    <Steps>
+      <Step status="finish" title="Login" icon={<IconTriangleDown />} />
+      <Step status="finish" title="Verification" icon={<IconClear />} />
+      <Step status="process" title="Pay" icon={<IconTick />} />
+      <Step status="wait" title="Done" icon={<IconClose />} />
+    </Steps>
+  );
+};
+
+StepsWithIcon.story = {
+  name: 'steps with icon',
 };
 
-stories.add('steps basic', () => <BasicStep />);
-stories.add('steps with icon', () => {
+const steps = [
+  {
+    title: 'First',
+    content: 'First-content',
+  },
+  {
+    title: 'Second',
+    content: 'Second-content',
+  },
+  {
+    title: 'Last',
+    content: 'Last-content',
+  },
+];
+
+class StepsDemo extends React.Component {
+  constructor(props) {
+    super(props);
+    this.state = {
+      current: 0,
+    };
+  }
+
+  next() {
+    const current = this.state.current + 1;
+    this.setState({
+      current,
+    });
+  }
+
+  prev() {
+    const current = this.state.current - 1;
+    this.setState({
+      current,
+    });
+  }
+
+  render() {
+    const { current } = this.state;
     return (
-        <Steps>
-            <Step status="finish" title="Login" icon={<IconTriangleDown />} />
-            <Step status="finish" title="Verification" icon={<IconClear />} />
-            <Step status="process" title="Pay" icon={<IconTick />} />
-            <Step status="wait" title="Done" icon={<IconClose />} />
+      <div>
+        <Steps current={current}>
+          {steps.map(item => (
+            <Step key={item.title} title={item.title} />
+          ))}
         </Steps>
+        <div className="steps-content">{steps[current].content}</div>
+        <div className="steps-action">
+          {current < steps.length - 1 && (
+            <Button type="primary" onClick={() => this.next()}>
+              Next
+            </Button>
+          )}
+          {current === steps.length - 1 && (
+            <Button type="primary" onClick={() => console.log('Processing complete!')}>
+              Done
+            </Button>
+          )}
+          {current > 0 && (
+            <Button
+              style={{
+                marginLeft: 8,
+              }}
+              onClick={() => this.prev()}
+            >
+              Previous
+            </Button>
+          )}
+        </div>
+      </div>
     );
-});
-const steps = [
-    {
+  }
+}
+
+export const StepsWithControled = () => {
+  return <StepsDemo></StepsDemo>;
+};
+
+StepsWithControled.story = {
+  name: 'steps with controled',
+};
+
+class StepsWithonChange extends React.Component {
+  constructor(props) {
+    super(props);
+    this.state = {
+      current: 1,
+    };
+  }
+
+  onChange(current) {
+    this.setState({ current });
+  }
+
+  render() {
+    const { current } = this.state;
+    const { Step } = Steps;
+    const steps = [
+      {
         title: 'First',
         content: 'First-content',
-    },
-    {
+      },
+      {
         title: 'Second',
         content: 'Second-content',
-    },
-    {
+      },
+      {
         title: 'Last',
         content: 'Last-content',
-    },
-];
+      },
+    ];
 
-class StepsDemo extends React.Component {
-    constructor(props) {
-        super(props);
-        this.state = {
-            current: 0,
-        };
-    }
-
-    next() {
-        const current = this.state.current + 1;
-        this.setState({
-            current,
-        });
-    }
-
-    prev() {
-        const current = this.state.current - 1;
-        this.setState({
-            current,
-        });
-    }
-
-    render() {
-        const { current } = this.state;
-        return (
-            <div>
-                <Steps current={current}>
-                    {steps.map(item => (
-                        <Step key={item.title} title={item.title} />
-                    ))}
-                </Steps>
-                <div className="steps-content">{steps[current].content}</div>
-                <div className="steps-action">
-                    {current < steps.length - 1 && (
-                        <Button type="primary" onClick={() => this.next()}>
-                            Next
-                        </Button>
-                    )}
-                    {current === steps.length - 1 && (
-                        <Button type="primary" onClick={() => console.log('Processing complete!')}>
-                            Done
-                        </Button>
-                    )}
-                    {current > 0 && (
-                        <Button
-                            style={{
-                                marginLeft: 8,
-                            }}
-                            onClick={() => this.prev()}
-                        >
-                            Previous
-                        </Button>
-                    )}
-                </div>
-            </div>
-        );
-    }
+    return (
+      <div>
+        <Steps type="basic" current={current} onChange={current => this.onChange(current)}>
+          {steps.map(item => (
+            <Step key={item.title} title={item.title} />
+          ))}
+        </Steps>
+      </div>
+    );
+  }
 }
 
-stories.add('steps with controled', () => {
-    return <StepsDemo></StepsDemo>;
-});
-
-class StepsWithonChange extends React.Component {
-    constructor(props) {
-        super(props);
-        this.state = {
-            current: 1,
-        };
-    }
-
-    onChange(current) {
-        this.setState({ current });
-    }
-
-    render() {
-        const { current } = this.state;
-        const { Step } = Steps;
-        const steps = [
-            {
-                title: 'First',
-                content: 'First-content',
-            },
-            {
-                title: 'Second',
-                content: 'Second-content',
-            },
-            {
-                title: 'Last',
-                content: 'Last-content',
-            },
-        ];
-
-        return (
-            <div>
-                <Steps type="basic" current={current} onChange={current => this.onChange(current)}>
-                    {steps.map(item => (
-                        <Step key={item.title} title={item.title} />
-                    ))}
-                </Steps>
-            </div>
-        );
-    }
-}
+export const StepsWithOnChange = () => {
+  return <StepsWithonChange />;
+};
 
-stories.add('steps with onChange', () => {
-    return <StepsWithonChange/>;
-});
+StepsWithOnChange.story = {
+  name: 'steps with onChange',
+};
 
 const StatusStep = () => {
-    return sizes.map(s => (
-        <Steps key={s} size={s} current={1} status="error">
-            <Step title="Finished" description="This is a description" />
-            <Step title="In Process" description="This is a description" />
-            <Step title="Waiting" description="This is a description" />
-        </Steps>
-    ));
+  return sizes.map(s => (
+    <Steps key={s} size={s} current={1} status="error">
+      <Step title="Finished" description="This is a description" />
+      <Step title="In Process" description="This is a description" />
+      <Step title="Waiting" description="This is a description" />
+    </Steps>
+  ));
 };
 
-stories.add('steps with status', () => <StatusStep />);
+export const StepsWithStatus = () => <StatusStep />;
+
+StepsWithStatus.story = {
+  name: 'steps with status',
+};
 
 const VerticalStep = () => {
-    return sizes.map(s => (
-        <Steps key={s} size={s} current={1} status="error" direction="vertical">
-            <Step title="Finished" description="This is a description" />
-            <Step title="In Process" description="This is a description" />
-            <Step title="Waiting" description="This is a description" />
-        </Steps>
-    ));
+  return sizes.map(s => (
+    <Steps key={s} size={s} current={1} status="error" direction="vertical">
+      <Step title="Finished" description="This is a description" />
+      <Step title="In Process" description="This is a description" />
+      <Step title="Waiting" description="This is a description" />
+    </Steps>
+  ));
 };
 
-stories.add('steps vertical', () => <VerticalStep />);
+export const StepsVertical = () => <VerticalStep />;
+
+StepsVertical.story = {
+  name: 'steps vertical',
+};
 
 const LineStep = () => {
-    return sizes.map(s => (
-        <Steps key={s} size={s} hasLine={false} current={1} status="error">
-            <Step title="Finished" description="This is a description" />
-            <Step title="In Process" description="This is a description" />
-            <Step title="Waiting" description="This is a description" />
-        </Steps>
-    ));
+  return sizes.map(s => (
+    <Steps key={s} size={s} hasLine={false} current={1} status="error">
+      <Step title="Finished" description="This is a description" />
+      <Step title="In Process" description="This is a description" />
+      <Step title="Waiting" description="This is a description" />
+    </Steps>
+  ));
 };
 
-stories.add('steps without line', () => <LineStep></LineStep>);
+export const StepsWithoutLine = () => <LineStep></LineStep>;
+
+StepsWithoutLine.story = {
+  name: 'steps without line',
+};

+ 144 - 108
packages/semi-ui/switch/_story/switch.stories.js

@@ -1,124 +1,160 @@
 import React, { useState } from 'react';
-import { Button } from '@douyinfe/semi-ui/';
-import {
-    storiesOf
-} from '@storybook/react';
-// import { withKnobs, text, boolean } from '@storybook/addon-knobs';
 
+import { Button } from '@douyinfe/semi-ui/';
 import { Switch } from '../../index';
 
-const stories = storiesOf('Switch', module);
-
-// stories.addDecorator(withKnobs);;
-
-stories.add('switch', () => (
-    <div>
-        <Switch onChange={(v, e) => console.log(v)}>
-        </Switch>
-        <Switch defaultChecked={true} onChange={(v, e) => console.log(v)}>
-        </Switch>
-    </div>
-));
-
-
-stories.add('switch size', () => (
-    <div>
-        <Switch onChange={(v, e) => console.log(v)}></Switch>
-        <Switch onChange={(v, e) => console.log(v)} size='small'></Switch>
-        <Switch onChange={(v, e) => console.log(v)} size='large'></Switch>
-    </div>
-));
-
-stories.add('switch checkedText &  uncheckedText', () => (
-    <div>
-        <Switch defaultChecked checkedText='开' uncheckedText='关' />
-        <Switch checkedText={'|'} uncheckedText='〇' />
-        <br/><br/>
-        <Switch checkedText='开' uncheckedText='关' />
-        <Switch defaultChecked checkedText='|' uncheckedText='〇' />
-        <br/><br/>
-        <Switch checkedText='开' uncheckedText='关' size='large' />
-        <Switch checkedText='|' uncheckedText='〇' size='large' />
-        <br/><br/>
-        <Switch defaultChecked checkedText='开' uncheckedText='关' size='large' />
-        <Switch defaultChecked checkedText='|' uncheckedText='〇' size='large' />
-    </div>
-));
-
-stories.add('switch disabled', () => (
-    <>
-        <Switch disabled>
-            disabled
-        </Switch>
+export default {
+  title: 'Switch'
+}
 
-        <Switch disabled checked={true} onChange={(v, e) => console.log(v)}>
-        </Switch>
-    </>
-));
+export const _Switch = () => (
+  <div>
+    <Switch onChange={(v, e) => console.log(v)}></Switch>
+    <Switch defaultChecked={true} onChange={(v, e) => console.log(v)}></Switch>
+  </div>
+);
+
+_Switch.story = {
+  name: 'switch',
+};
+
+export const SwitchSize = () => (
+  <div>
+    <Switch onChange={(v, e) => console.log(v)}></Switch>
+    <Switch onChange={(v, e) => console.log(v)} size="small"></Switch>
+    <Switch onChange={(v, e) => console.log(v)} size="large"></Switch>
+  </div>
+);
 
+SwitchSize.story = {
+  name: 'switch size',
+};
+
+export const SwitchCheckedTextUncheckedText = () => (
+  <div>
+    <Switch defaultChecked checkedText="开" uncheckedText="关" />
+    <Switch checkedText={'|'} uncheckedText="〇" />
+    <br />
+    <br />
+    <Switch checkedText="开" uncheckedText="关" />
+    <Switch defaultChecked checkedText="|" uncheckedText="〇" />
+    <br />
+    <br />
+    <Switch checkedText="开" uncheckedText="关" size="large" />
+    <Switch checkedText="|" uncheckedText="〇" size="large" />
+    <br />
+    <br />
+    <Switch defaultChecked checkedText="开" uncheckedText="关" size="large" />
+    <Switch defaultChecked checkedText="|" uncheckedText="〇" size="large" />
+  </div>
+);
+
+SwitchCheckedTextUncheckedText.story = {
+  name: 'switch checkedText &  uncheckedText',
+};
+
+export const SwitchDisabled = () => (
+  <>
+    <Switch disabled>disabled</Switch>
+
+    <Switch disabled checked={true} onChange={(v, e) => console.log(v)}></Switch>
+  </>
+);
+
+SwitchDisabled.story = {
+  name: 'switch disabled',
+};
 
 const ControledSwitch = () => {
-    const [checked, onChange] = useState(true);
-    return (
-        <Switch checked={checked} onChange={(v, e) => onChange(v)} />
-    );
+  const [checked, onChange] = useState(true);
+  return <Switch checked={checked} onChange={(v, e) => onChange(v)} />;
+};
+export const SwitchCheckedOnChange = () => <ControledSwitch />;
+
+SwitchCheckedOnChange.story = {
+  name: 'switch checked + onChange',
 };
-stories.add('switch checked + onChange', () => <ControledSwitch/>);
 
 const UnControledSwitch = () => {
-    const onChange = checked => {
-        console.log(checked);
-    };
-    return (
-        <>
-            {/* <Switch onChange={onChange} defaultChecked={false}/> */}
-            <Switch onChange={onChange} defaultChecked={true}/>
-        </>
-    );
+  const onChange = checked => {
+    console.log(checked);
+  };
+  return (
+    <>
+      {/* <Switch onChange={onChange} defaultChecked={false}/> */}
+      <Switch onChange={onChange} defaultChecked={true} />
+    </>
+  );
+};
+export const SwitchDefaultCheckedOnChange = () => <UnControledSwitch />;
+
+SwitchDefaultCheckedOnChange.story = {
+  name: 'switch defaultChecked + onChange',
 };
-stories.add('switch defaultChecked + onChange', () => <UnControledSwitch/>);
 
 class LoadingDemo extends React.Component {
-    constructor() {
-        super()
-        this.state = {
-            checked: true,
-            loading:false
-        }
-        this.onChange = this.onChange.bind(this);
-    }
-    onChange(checked) {
-        this.setState({ checked });
-    }
-    render() {
-        return (
-            <>
-                <Button onClick={() => { this.setState({ checked: true }); }}>
-                    checked
-                </Button>
-                <br /><br />
-                <Button onClick={() => { this.setState({ checked: false }); }}>
-                    unchecked
-                </Button>
-                <br /><br />
-                <Button onClick={() => { this.setState({ loading: !this.state.loading }); }}>
-                    loading
-                </Button>
-                <br /><br />
-                <Switch
-                    checked={this.state.checked}
-                    onChange={this.onChange}
-                    loading={this.state.loading}>
-                </Switch>
-                <br /><br />
-                <hr />
-                <Switch loading disabled/>
-                <br /><br />
-                <Switch loading disabled defaultChecked/>
-                <br /><br />
-            </>
-        )
-    }
+  constructor() {
+    super();
+    this.state = {
+      checked: true,
+      loading: false,
+    };
+    this.onChange = this.onChange.bind(this);
+  }
+  onChange(checked) {
+    this.setState({ checked });
+  }
+  render() {
+    return (
+      <>
+        <Button
+          onClick={() => {
+            this.setState({ checked: true });
+          }}
+        >
+          checked
+        </Button>
+        <br />
+        <br />
+        <Button
+          onClick={() => {
+            this.setState({ checked: false });
+          }}
+        >
+          unchecked
+        </Button>
+        <br />
+        <br />
+        <Button
+          onClick={() => {
+            this.setState({ loading: !this.state.loading });
+          }}
+        >
+          loading
+        </Button>
+        <br />
+        <br />
+        <Switch
+          checked={this.state.checked}
+          onChange={this.onChange}
+          loading={this.state.loading}
+        ></Switch>
+        <br />
+        <br />
+        <hr />
+        <Switch loading disabled />
+        <br />
+        <br />
+        <Switch loading disabled defaultChecked />
+        <br />
+        <br />
+      </>
+    );
+  }
 }
 
-stories.add('loading', () => <LoadingDemo/>);
+export const Loading = () => <LoadingDemo />;
+
+Loading.story = {
+  name: 'loading',
+};

+ 1 - 1
packages/semi-ui/table/_story/BetterScrollbar.tsx

@@ -68,7 +68,7 @@ function App() {
     const data = [];
     
     for (let i = 0; i < 10; i++) {
-        const age = 40 + (Math.random() > 0.5 ? 1 : -1) * (i % 9);
+        const age = (i * 1000) % 149 ;
         const name = `Edward King ${i}`;
         data.push({
             key: `${ i}`,

+ 1 - 1
packages/semi-ui/table/_story/CustomComponents/index.js

@@ -39,7 +39,7 @@ const Demo = () => {
     const data = useMemo(() => {
         const _data = [];
         for (let i = 0; i < dataTotalSize; i++) {
-            let age = 40 + (Math.random() > 0.5 ? 1 : -1) * Math.ceil(i / 3);
+            let age = (i * 1000) % 149 ;
             let name = `Edward King ${i}`;
             _data.push({
                 key: '' + i,

+ 1 - 1
packages/semi-ui/table/_story/CustomFilterDropdownItem/index.jsx

@@ -71,7 +71,7 @@ export default class CustomDropdownItem extends React.Component {
         };
 
         for (let i = 0; i < 46; i++) {
-            let age = 40 + (Math.random() > 0.5 ? 1 : -1) * Math.ceil(i / 3);
+            let age = (i * 1000) % 149 ;
             let name = `Edward King ${i}`;
             this.data.push({
                 key: '' + i,

+ 1 - 1
packages/semi-ui/table/_story/DynamicTable/index.jsx

@@ -32,7 +32,7 @@ export default class App extends React.Component {
 
         const data = [];
         for (let i = 0; i < dataTotalSize; i++) {
-            let age = 40 + (Math.random() > 0.5 ? 1 : -1) * Math.ceil(i / 3);
+            let age = (i * 1000) % 149 ;
             let name = `Edward King ${i}`;
             data.push({
                 key: '' + i,

+ 1 - 1
packages/semi-ui/table/_story/EventTable/index.jsx

@@ -37,7 +37,7 @@ function EventTable(props = {}) {
     const data = useMemo(() => {
         const _data = [];
         for (let i = 0; i < dataTotalSize; i++) {
-            let age = 40 + (Math.random() > 0.5 ? 1 : -1) * Math.ceil(i / 3);
+            let age = (i * 1000) % 149 ;
             let name = `Edward King ${i}`;
             _data.push({
                 key: '' + i,

+ 1 - 1
packages/semi-ui/table/_story/ExpandAllRows/index.jsx

@@ -61,7 +61,7 @@ export default function App() {
     const getData = () => {
         let newData = [];
         for (let i = 0; i < 46; i++) {
-            let age = 40 + (Math.random() > 0.5 ? 1 : -1) * Math.ceil(i / 3);
+            let age = (i * 1000) % 149 ;
             let name = `Edward King ${i}`;
             newData.push({
                 key: `${i}`,

+ 1 - 1
packages/semi-ui/table/_story/FixAllColumnsWithoutWidth.tsx

@@ -32,7 +32,7 @@ function App() {
     const data = [];
 
     for (let i = 0; i < 8; i++) {
-        const age = 40 + (Math.random() > 0.5 ? 1 : -1) * Math.ceil(i / 3);
+        const age = (i * 1000) % 149 ;
         const name = `Edward King ${i}`;
         data.push({
             key: `${i}`,

+ 1 - 1
packages/semi-ui/table/_story/FixedExpandedRows/index.js

@@ -69,7 +69,7 @@ export default class FixedTableApp extends React.Component {
         };
 
         for (let i = 0; i < 46; i++) {
-            let age = 40 + (Math.random() > 0.5 ? 1 : -1) * Math.ceil(i / 3);
+            let age = (i * 1000) % 149 ;
             let name = `Edward King ${i}`;
             this.data.push({
                 key: '' + i,

+ 1 - 1
packages/semi-ui/table/_story/FixedTable/index.js

@@ -71,7 +71,7 @@ export default class FixedTableApp extends React.Component {
         };
 
         for (let i = 0; i < 46; i++) {
-            let age = 40 + (Math.random() > 0.5 ? 1 : -1) * Math.ceil(i / 3);
+            let age = (i * 1000) % 149 ;
             let name = `Edward King ${i}`;
             this.data.push({
                 key: `${ i}`,

+ 1 - 1
packages/semi-ui/table/_story/FullRender/index.jsx

@@ -25,7 +25,7 @@ export default function Demo(props = {}) {
         const data = [];
         for (let i = 0; i < total; i++) {
             const no = i + 1;
-            const age = 40 + (Math.random() > 0.5 ? 1 : -1) * (i % 9);
+            const age = (i * 1000) % 149 ;
             const name = `Edward King ${i}`;
             const childrenCount = i % 4;
             const children = [];

+ 1 - 1
packages/semi-ui/table/_story/GroupedColsFixed/index.jsx

@@ -62,7 +62,7 @@ export default function Demo() {
     const data = useMemo(() => {
         const data = [];
         for (let i = 0; i < 100; i++) {
-            let age = 40 + (Math.random() > 0.5 ? 1 : -1) * (i % 9);
+            let age = (i * 1000) % 149 ;
             let name = `Edward King ${i}`;
             data.push({
                 key: '' + i,

+ 1 - 1
packages/semi-ui/table/_story/GroupedColsFixedJSX/index.jsx

@@ -5,7 +5,7 @@ export default function Demo() {
     const data = useMemo(() => {
         const data = [];
         for (let i = 0; i < 100; i++) {
-            let age = 40 + (Math.random() > 0.5 ? 1 : -1) * (i % 9);
+            let age = (i * 1000) % 149 ;
             let name = `Edward King ${i}`;
             data.push({
                 key: '' + i,

+ 1 - 1
packages/semi-ui/table/_story/GroupedColsFixedVirtualized/index.jsx

@@ -63,7 +63,7 @@ export default function Demo() {
     const data = useMemo(() => {
         const data = [];
         for (let i = 0; i < total; i++) {
-            let age = 40 + (Math.random() > 0.5 ? 1 : -1) * (i % 9);
+            let age = (i * 1000) % 149 ;
             let name = `Edward King ${i}`;
             data.push({
                 key: '' + i,

+ 1 - 1
packages/semi-ui/table/_story/GroupedColsFixedVirtualizedGroups/index.jsx

@@ -63,7 +63,7 @@ export default function Demo() {
     const data = useMemo(() => {
         const data = [];
         for (let i = 0; i < total; i++) {
-            let age = 40 + (Math.random() > 0.5 ? 1 : -1) * (i % 9);
+            let age = (i * 1000) % 149 ;
             let name = `Edward King ${i}`;
             data.push({
                 key: 'row' + i,

+ 1 - 1
packages/semi-ui/table/_story/InSideSheet/index.jsx

@@ -45,7 +45,7 @@ export default function Demo(props = {}) {
     const data = useMemo(() => {
         const _data = [];
         for (let i = 0; i < dataTotalSize; i++) {
-            let age = 40 + (Math.random() > 0.5 ? 1 : -1) * Math.ceil(i / 3);
+            let age = (i * 1000) % 149 ;
             let name = `Edward King ${i}`;
             _data.push({
                 key: '' + i,

+ 1 - 1
packages/semi-ui/table/_story/InfiniteScroll/index.js

@@ -80,7 +80,7 @@ class InfiniteScrollDemo extends React.Component {
         const data = [...this.state.data];
         const currentLenght = data.length;
         for (let i = currentLenght; i < currentLenght + pageSize; i++) {
-            let age = 40 + (Math.random() > 0.5 ? 1 : -1) * (i % 9);
+            let age = (i * 1000) % 149 ;
             let name = `Edward King ${i}`;
             data.push({
                 key: '' + i,

+ 1 - 1
packages/semi-ui/table/_story/JSXColumnsComplex.jsx

@@ -27,7 +27,7 @@ export default class JSXColumnsComplex extends React.Component {
             this.data.push({
                 key: `${i}`,
                 name: `Edward King ${i}`,
-                age: 40 + (Math.random() > 0.5 ? 1 : -1) * Math.ceil(i / 3),
+                age: (i * 1000) % 149 ,
                 address: `London, Park Lane no. ${i}`,
             });
         }

+ 1 - 1
packages/semi-ui/table/_story/JSXColumnsNest.tsx

@@ -6,7 +6,7 @@ const JSXColumnsNest: React.FunctionComponent = () => {
     const data = useMemo(() => {
         const _data = [];
         for (let i = 0; i < 100; i++) {
-            const age = 40 + (Math.random() > 0.5 ? 1 : -1) * (i % 9);
+            const age = (i * 1000) % 149 ;
             const name = `Edward King ${i}`;
             _data.push({
                 key: `${ i}`,

+ 1 - 1
packages/semi-ui/table/_story/JSXTitles/index.js

@@ -7,7 +7,7 @@ const dataTotalSize = 46;
 const data = (() => {
     const _data = [];
     for (let i = 0; i < dataTotalSize; i++) {
-        let age = 40 + (Math.random() > 0.5 ? 1 : -1) * Math.ceil(i / 3);
+        let age = (i * 1000) % 149 ;
         let name = `Edward King ${i}`;
         _data.push({
             key: '' + i,

+ 4 - 0
packages/semi-ui/table/_story/MassiveColumns/index.jsx

@@ -102,4 +102,8 @@ const Demo = () => {
     );
 };
 
+Demo.parameters = {
+    chromatic: { disableSnapshot: true },
+}
+
 export default Demo;

+ 1 - 1
packages/semi-ui/table/_story/ModalTable/index.jsx

@@ -41,7 +41,7 @@ function ModalTable() {
     ];
     // const data = [];
     // for (let i = 0; i < dataTotalSize; i++) {
-    //     let age = 40 + (Math.random() > 0.5 ? 1 : -1) * Math.ceil(i / 3);
+    //     let age = (i * 1000) % 149 ;
     //     let name = `Edward King ${i}`;
     //     data.push({
     //         key: '' + new Date().toString(16),

+ 4 - 0
packages/semi-ui/table/_story/RTL/AlignScrollBar.jsx

@@ -10,4 +10,8 @@ const App = function (props) {
     );
 };
 
+App.parameters = {
+    chromatic: { disableSnapshot: true },
+}
+
 export default App;

+ 1 - 1
packages/semi-ui/table/_story/ResizableTable/index.jsx

@@ -55,7 +55,7 @@ export default class ResizableDemo extends React.Component {
         };
 
         for (let i = 0; i < 46; i++) {
-            let age = 40 + (Math.random() > 0.5 ? 1 : -1) * Math.ceil(i / 3);
+            let age = (i * 1000) % 149 ;
             let name = `Edward King ${i}`;
             this.data.push({
                 key: `${ i}`,

+ 1 - 1
packages/semi-ui/table/_story/SelectedRows/index.js

@@ -46,7 +46,7 @@ function App() {
     const data = useMemo(() => {
         const _data = [];
         for (let i = 0; i < dataTotalSize; i++) {
-            let age = 40 + (Math.random() > 0.5 ? 1 : -1) * Math.ceil(i / 3);
+            let age = (i * 1000) % 149 ;
             let name = `Edward King ${i}`;
             _data.push({
                 key: '' + i,

+ 1 - 1
packages/semi-ui/table/_story/TabsTable/index.jsx

@@ -39,7 +39,7 @@ function AsyncTable(props = {}) {
         setTimeout(() => {
             const _data = [];
             for (let i = 0; i < dataTotalSize; i++) {
-                let age = 40 + (Math.random() > 0.5 ? 1 : -1) * Math.ceil(i / 3);
+                let age = (i * 1000) % 149 ;
                 let name = `Edward King ${i}`;
                 _data.push({
                     key: '' + i,

+ 1 - 1
packages/semi-ui/table/_story/VirtualTableOnCell/index.jsx

@@ -54,7 +54,7 @@ export default class VirtualizedFixedDemo extends React.Component {
         this.data = [];
 
         for (let i = 0; i < 1000; i++) {
-            let age = 40 + (Math.random() > 0.5 ? 1 : -1) * (i % 9);
+            let age = (i * 1000) % 149 ;
             let name = `Edward King ${i}`;
             this.data.push({
                 key: '' + i,

+ 4 - 0
packages/semi-ui/table/_story/VirtualizedDynamicData/index.jsx

@@ -1,6 +1,10 @@
 import React, { useMemo, useState, useEffect, useRef } from 'react';
 import { Table, Tooltip, Tag, Avatar } from '../../../index';
 
+Demo.parameters = {
+    chromatic: { disableSnapshot: true },
+}
+
 export default function Demo() {
     const [counter, setCounter] = useState(1);
     const scrollingRef = useRef(false);

+ 1 - 1
packages/semi-ui/table/_story/VirtualizedNotFixed/index.js

@@ -48,7 +48,7 @@ export default class Demo extends React.Component {
         this.data = [];
 
         for (let i = 0; i < 1000; i++) {
-            let age = 40 + (Math.random() > 0.5 ? 1 : -1) * (i % 9);
+            let age = (i * 1000) % 149 ;
             let name = `Edward King ${i}`;
             this.data.push({
                 key: '' + i,

+ 1 - 1
packages/semi-ui/table/_story/WithSideSheet/index.js

@@ -56,7 +56,7 @@ export default function Demo(props = {}) {
     const data = useMemo(() => {
         const _data = [];
         for (let i = 0; i < dataTotalSize; i++) {
-            let age = 40 + (Math.random() > 0.5 ? 1 : -1) * Math.ceil(i / 3);
+            let age = (i * 1000) % 149 ;
             let name = `Edward King ${i}`;
             _data.push({
                 key: `${ i}`,

+ 511 - 353
packages/semi-ui/table/_story/table.stories.js

@@ -1,7 +1,6 @@
 import React from 'react';
-import {storiesOf} from '@storybook/react';
-// import { withKnobs, text, boolean } from '@storybook/addon-knobs';
-import {Table} from '@douyinfe/semi-ui';
+
+import { Table } from '@douyinfe/semi-ui';
 
 import JSXColumnsSimple from './JSXColumnsSmiple';
 import JSXColumnsComplex from './JSXColumnsComplex';
@@ -22,415 +21,574 @@ import PaginationDemo from './PagintaionTable';
 import SelectedRowsDemo from './SelectedRows';
 import ChildrenData from './ChildrenData';
 import ChildrenDataSelected from './ChildrenDataSelected';
-import WithSideSheet from './WithSideSheet';
-import InSideSheet from './InSideSheet';
-import GroupedCols from './GroupedCols';
-import GroupedColsFixed from './GroupedColsFixed';
-import GroupedColsFixedJSX from './GroupedColsFixedJSX';
-import GroupedColsFixedVirtualized from './GroupedColsFixedVirtualized';
-import GroupedColsFixedVirtualizedGroups from './GroupedColsFixedVirtualizedGroups';
-import GroupedRows from './GroupedRows';
-import GroupedRowsFixed from './GroupedRowsFixed';
-import FixedGroups from './FixedGroups';
 import FixedExpandedRows from './FixedExpandedRows';
 import FixedTable from './FixedTable';
 import JSXFixedTable from './JSXFixedTable';
 import JSXTitles from './JSXTitles';
-import CustomComponents from './CustomComponents';
-import CustomExpandIcons from './CustomExpandIcons';
 import CustomFilterDropdownItem from './CustomFilterDropdownItem';
-
 import VirtualizedDemo from './virtualized';
-import VirtualizedFixedDemo from './virtualizedFixed';
-import VirtualizedNotFixedDemo from './VirtualizedNotFixed';
-import VirtualizedGroupedRows from './VirtualizedGroupedRows';
-import VirtualizedDataSelected from './VritualizedDataSelected';
-import VirtualizedDynamicData from './VirtualizedDynamicData';
+import VirtualizedNotFixed from './VirtualizedNotFixed';
 import InfiniteScroll from './InfiniteScroll';
-import MassiveColumns from './MassiveColumns';
-import ControlledPagination from './ControlledPagination';
-import FulldRenderDemo from './FullRender';
 import VirtualTableOnCell from './VirtualTableOnCell';
 import {
-    ControlledSelection,
-    PerfComplexRender,
-    PerfContext,
-    PerfOnRow,
-    PerfRender,
-    PerfResizableSelection,
-    PerfVirtualized
+  ControlledSelection,
+  PerfComplexRender,
+  PerfContext,
+  PerfOnRow,
+  PerfRender,
+  PerfResizableSelection,
+  PerfVirtualized,
 } from './Perf';
-import RenderPagination from './RenderPagination'
-import {RTLAlignScrollBar} from './RTL';
-import JSXAsyncData from './JSXAsyncData';
-import ScrollBar from './ScrollBar';
-import TableSpan from './TableSpan';
+import RenderPagination from './RenderPagination';
 import ControlledSortOrder from './ControlledSortOrder';
 import FilterWithNewDataTable from './FilterWithNewDataTable';
-import FixRenderReturnProps from './FixRenderReturnProps';
 import ExpandAllRows from './ExpandAllRows';
 import ExpandAllGroupRows from './ExpandAllGroupRows';
 import ExpandRowByClick from './ExpandRowByClick';
 import FixAllColumnsWithoutWidth from './FixAllColumnsWithoutWidth';
 
-const stories = storiesOf('Table', module);
-// // stories.addDecorator(withKnobs);;
+export default {
+  title: 'Table'
+}
+
+export { default as WithSideSheet } from './WithSideSheet';
+export { default as InSideSheet } from './InSideSheet';
+export { default as GroupedCols } from './GroupedCols';
+export { default as GroupedColsFixed } from './GroupedColsFixed';
+export { default as GroupedColsFixedJSX } from './GroupedColsFixedJSX';
+export { default as GroupedColsFixedVirtualized } from './GroupedColsFixedVirtualized';
+export { default as GroupedColsFixedVirtualizedGroups } from './GroupedColsFixedVirtualizedGroups';
+export { default as GroupedRows } from './GroupedRows';
+export { default as GroupedRowsFixed } from './GroupedRowsFixed';
+export { default as FixedGroups } from './FixedGroups';
+export { default as CustomComponents } from './CustomComponents';
+export { default as CustomExpandIcons } from './CustomExpandIcons';
+export { default as VirtualizedFixedDemo } from './virtualizedFixed';
+export { default as VirtualizedGroupedRows } from './VirtualizedGroupedRows';
+export { default as VirtualizedDataSelected } from './VritualizedDataSelected';
+export { default as VirtualizedDynamicData } from './VirtualizedDynamicData';
+export { default as MassiveColumns } from './MassiveColumns';
+export { default as ControlledPagination } from './ControlledPagination';
+export { default as FulldRenderDemo } from './FullRender';
+export { RTLAlignScrollBar } from './RTL';
+export { default as JSXAsyncData } from './JSXAsyncData';
+export { default as ScrollBar } from './ScrollBar';
+export { default as TableSpan } from './TableSpan';
+export { default as FixRenderReturnProps } from './FixRenderReturnProps';
 
 // empty table
 
 const emptyColumn = [
-    {
-        title: 'Name',
-        dataIndex: 'name',
-        fixed: 'left',
-        render: text => <a>{text}</a>,
-    },
-    {
-        title: 'Age',
-        dataIndex: 'age',
-    },
-    {
-        title: 'Address',
-        dataIndex: 'address',
-    },
+  {
+    title: 'Name',
+    dataIndex: 'name',
+    fixed: 'left',
+    render: text => <a>{text}</a>,
+  },
+  {
+    title: 'Age',
+    dataIndex: 'age',
+  },
+  {
+    title: 'Address',
+    dataIndex: 'address',
+  },
 ];
 const emptyData = [];
 
-stories.add('empty table', () => <Table autoWidth columns={emptyColumn} dataSource={emptyData}/>);
+export const EmptyTable = () => <Table autoWidth columns={emptyColumn} dataSource={emptyData} />;
+
+EmptyTable.story = {
+  name: 'empty table',
+};
 
 // basic table
 
 const columns = [
-    {
-        title: 'Name',
-        dataIndex: 'name',
-        width: '30%',
-        render: text => <a>{text}</a>,
-    },
-    {
-        title: 'combine',
+  {
+    title: 'Name',
+    dataIndex: 'name',
+    width: '30%',
+    render: text => <a>{text}</a>,
+  },
+  {
+    title: 'combine',
+    width: '20%',
+    dataIndex: 'test',
+    children: [
+      {
+        title: 'Age',
         width: '20%',
-        dataIndex: 'test',
         children: [
-            {
-                title: 'Age',
-                width: '20%',
-                children: [
-                    {
-                        title: 'Age1',
-                        width: '20%',
-                        dataIndex: 'age1',
-                    },
-                    {
-                        title: 'Age2',
-                        width: '20%',
-                        dataIndex: 'age2',
-                    },
-                ],
-            },
-            {
-                title: 'Key',
-                width: '20%',
-                dataIndex: 'key',
-            },
+          {
+            title: 'Age1',
+            width: '20%',
+            dataIndex: 'age1',
+          },
+          {
+            title: 'Age2',
+            width: '20%',
+            dataIndex: 'age2',
+          },
         ],
-    },
-    {
-        title: 'Address',
-        width: '50%',
-        dataIndex: 'address',
-    },
+      },
+      {
+        title: 'Key',
+        width: '20%',
+        dataIndex: 'key',
+      },
+    ],
+  },
+  {
+    title: 'Address',
+    width: '50%',
+    dataIndex: 'address',
+  },
 ];
 const data = [
-    {
-        key: '1',
-        name: 'John Brown',
-        age: 32,
-        age1: 23,
-        age2: 11,
-        address: 'New York No. 1 Lake Park, New York No. 1 Lake Park',
-    },
-    {
-        key: '2',
-        name: 'Jim Green',
-        age: 42,
-        age1: 23,
-        age2: 11,
-        address: 'London No. 1 Lake Park',
-    },
-    {
-        key: '3',
-        name: 'Joe Black',
-        age: 32,
-        age1: 23,
-        age2: 11,
-        address: 'Sidney No. 1 Lake Park',
-    },
-    {
-        key: '4',
-        name: 'Disabled User',
-        age: 99,
-        age1: 23,
-        age2: 11,
-        address: 'Sidney No. 1 Lake Park',
-    },
+  {
+    key: '1',
+    name: 'John Brown',
+    age: 32,
+    age1: 23,
+    age2: 11,
+    address: 'New York No. 1 Lake Park, New York No. 1 Lake Park',
+  },
+  {
+    key: '2',
+    name: 'Jim Green',
+    age: 42,
+    age1: 23,
+    age2: 11,
+    address: 'London No. 1 Lake Park',
+  },
+  {
+    key: '3',
+    name: 'Joe Black',
+    age: 32,
+    age1: 23,
+    age2: 11,
+    address: 'Sidney No. 1 Lake Park',
+  },
+  {
+    key: '4',
+    name: 'Disabled User',
+    age: 99,
+    age1: 23,
+    age2: 11,
+    address: 'Sidney No. 1 Lake Park',
+  },
 ];
 
-stories.add('basic table', () => <Table columns={columns} dataSource={data}/>);
+export const BasicTable = () => <Table columns={columns} dataSource={data} />;
 
-stories.add('simple jsx', () => <JSXColumnsSimple/>);
+BasicTable.story = {
+  name: 'basic table',
+};
 
-stories.add('complex jsx', () => <JSXColumnsComplex/>);
+export const SimpleJsx = () => <JSXColumnsSimple />;
+
+SimpleJsx.story = {
+  name: 'simple jsx',
+};
+
+export const ComplexJsx = () => <JSXColumnsComplex />;
+
+ComplexJsx.story = {
+  name: 'complex jsx',
+};
+
+ComplexJsx.parameters = {
+  chromatic: { disableSnapshot: true },
+}
 
 // selection table
 
 // rowSelection object indicates the need for row selection
 const rowSelection = {
-    onChange: (selectedRowKeys, selectedRows) => {
-        // console.log(`selectedRowKeys: ${selectedRowKeys}`, 'selectedRows: ', selectedRows);
-    },
-    getCheckboxProps: record => ({
-        disabled: record.name === 'Disabled User', // Column configuration not to be checked
-        name: record.name,
-    }),
+  onChange: (selectedRowKeys, selectedRows) => {
+    // console.log(`selectedRowKeys: ${selectedRowKeys}`, 'selectedRows: ', selectedRows);
+  },
+  getCheckboxProps: record => ({
+    disabled: record.name === 'Disabled User', // Column configuration not to be checked
+    name: record.name,
+  }),
 };
-stories.add('filter and update dataSource', () => <FilterWithNewDataTable/>);
-stories.add('selection table', () => <Table rowSelection={rowSelection} columns={columns} dataSource={data}/>);
+export const FilterAndUpdateDataSource = () => <FilterWithNewDataTable />;
 
-function ControlledSelectionTable() {
-    const [selected, setSelected] = React.useState([]);
-    const columns = [
-        {
-            title: 'Name',
-            dataIndex: 'name',
-            render: text => text,
-        },
-        {
-            title: 'Age',
-            dataIndex: 'age',
-        },
-        {
-            title: 'Address',
-            dataIndex: 'address',
-        },
-    ];
-    const data = [
-        {
-            key: '1',
-            name: 'John Brown',
-            age: 32,
-            address: 'New York No. 1 Lake Park, New York No. 1 Lake Park',
-        },
-        {
-            key: '2',
-            name: 'Jim Green',
-            age: 42,
-            address: 'London No. 1 Lake Park',
-        },
-        {
-            key: '3',
-            name: 'Joe Black',
-            age: 32,
-            address: 'Sidney No. 1 Lake Park',
-        },
-        {
-            key: '4',
-            name: 'Michael James',
-            age: 99,
-            address: 'Sidney No. 1 Lake Park',
-        },
-    ];
-    const rowSelection = {
-        onChange: (selectedRowKeys, selectedRows) => {
-            setSelected(selectedRowKeys);
-        },
-        getCheckboxProps: record => ({
-            disabled:
-                selected.length === 2 &&
-                selected.findIndex(key => key === record.key) === -1, // Column configuration not to be checked
-            name: record.name,
-        }),
-        selectedRowKeys: selected
-    };
-    return <Table columns={columns} dataSource={data} rowSelection={rowSelection} pagination={false}/>;
-}
+FilterAndUpdateDataSource.story = {
+  name: 'filter and update dataSource',
+};
 
-stories.add('controlled selection table', () => <ControlledSelectionTable/>);
-// sortable table
+export const SelectionTable = () => (
+  <Table rowSelection={rowSelection} columns={columns} dataSource={data} />
+);
 
-const sortColumns = [
+SelectionTable.story = {
+  name: 'selection table',
+};
+
+function ControlledSelectionTable() {
+  const [selected, setSelected] = React.useState([]);
+  const columns = [
     {
-        title: 'Name',
-        dataIndex: 'name',
-        filters: [
-            {
-                text: 'XiaoMing',
-                value: 'XiaoMing',
-            },
-            {
-                text: 'ZhangSan',
-                value: 'ZhangSan',
-            },
-            {
-                text: 'SubMenu',
-                value: 'SubMenu',
-                children: [
-                    {
-                        text: 'Yellow',
-                        value: 'Yellow',
-                    },
-                    {
-                        text: 'Pink',
-                        value: 'Pink',
-                    },
-                ],
-            },
-        ],
-        onFilter: (value, record) => record.name.indexOf(value) === 0,
-        sorter: (a, b) => a.name.length - b.name.length,
-        sortDirections: ['descend'],
-        sortOrder: 'descend',
+      title: 'Name',
+      dataIndex: 'name',
+      render: text => text,
     },
     {
-        title: 'Age',
-        dataIndex: 'age',
-        defaultSortOrder: 'descend',
-        sorter: (a, b) => a.age - b.age,
+      title: 'Age',
+      dataIndex: 'age',
     },
     {
-        title: 'Address',
-        dataIndex: 'address',
-        filters: [
-            {
-                text: 'BieJing',
-                value: 'BeiJing',
-            },
-            {
-                text: 'ShangHai',
-                value: 'SHangHai',
-            },
-        ],
-        filterMultiple: false,
-        onFilter: (value, record) => record.address.indexOf(value) === 0,
-        sorter: (a, b) => a.address.length - b.address.length,
-        sortDirections: ['descend', 'ascend'],
+      title: 'Address',
+      dataIndex: 'address',
     },
-];
-
-const sortData = [
+  ];
+  const data = [
     {
-        key: '1',
-        name: 'ZhangSan',
-        age: 50,
-        address: 'BeiJing No.1 High School',
+      key: '1',
+      name: 'John Brown',
+      age: 32,
+      address: 'New York No. 1 Lake Park, New York No. 1 Lake Park',
     },
     {
-        key: '2',
-        name: 'LiSi',
-        age: 60,
-        address: 'BeiJing No.2 High School',
+      key: '2',
+      name: 'Jim Green',
+      age: 42,
+      address: 'London No. 1 Lake Park',
     },
     {
-        key: '3',
-        name: 'WangWu',
-        age: 20,
-        address: 'BeiJing No.3 High School',
+      key: '3',
+      name: 'Joe Black',
+      age: 32,
+      address: 'Sidney No. 1 Lake Park',
     },
     {
-        key: '4',
-        name: 'XiaoMing',
-        age: 30,
-        address: 'BeiJing No.5 High School',
+      key: '4',
+      name: 'Michael James',
+      age: 99,
+      address: 'Sidney No. 1 Lake Park',
     },
+  ];
+  const rowSelection = {
+    onChange: (selectedRowKeys, selectedRows) => {
+      setSelected(selectedRowKeys);
+    },
+    getCheckboxProps: record => ({
+      disabled: selected.length === 2 && selected.findIndex(key => key === record.key) === -1, // Column configuration not to be checked
+      name: record.name,
+    }),
+    selectedRowKeys: selected,
+  };
+  return (
+    <Table columns={columns} dataSource={data} rowSelection={rowSelection} pagination={false} />
+  );
+}
+
+export const _ControlledSelectionTable = () => <ControlledSelectionTable />;
+
+_ControlledSelectionTable.story = {
+  name: 'controlled selection table',
+};
+_ControlledSelectionTable.parameters = {
+  chromatic: { disableSnapshot: true },
+}
+
+// sortable table
+
+const sortColumns = [
+  {
+    title: 'Name',
+    dataIndex: 'name',
+    filters: [
+      {
+        text: 'XiaoMing',
+        value: 'XiaoMing',
+      },
+      {
+        text: 'ZhangSan',
+        value: 'ZhangSan',
+      },
+      {
+        text: 'SubMenu',
+        value: 'SubMenu',
+        children: [
+          {
+            text: 'Yellow',
+            value: 'Yellow',
+          },
+          {
+            text: 'Pink',
+            value: 'Pink',
+          },
+        ],
+      },
+    ],
+    onFilter: (value, record) => record.name.indexOf(value) === 0,
+    sorter: (a, b) => a.name.length - b.name.length,
+    sortDirections: ['descend'],
+    sortOrder: 'descend',
+  },
+  {
+    title: 'Age',
+    dataIndex: 'age',
+    defaultSortOrder: 'descend',
+    sorter: (a, b) => a.age - b.age,
+  },
+  {
+    title: 'Address',
+    dataIndex: 'address',
+    filters: [
+      {
+        text: 'BieJing',
+        value: 'BeiJing',
+      },
+      {
+        text: 'ShangHai',
+        value: 'SHangHai',
+      },
+    ],
+    filterMultiple: false,
+    onFilter: (value, record) => record.address.indexOf(value) === 0,
+    sorter: (a, b) => a.address.length - b.address.length,
+    sortDirections: ['descend', 'ascend'],
+  },
+];
+
+const sortData = [
+  {
+    key: '1',
+    name: 'ZhangSan',
+    age: 50,
+    address: 'BeiJing No.1 High School',
+  },
+  {
+    key: '2',
+    name: 'LiSi',
+    age: 60,
+    address: 'BeiJing No.2 High School',
+  },
+  {
+    key: '3',
+    name: 'WangWu',
+    age: 20,
+    address: 'BeiJing No.3 High School',
+  },
+  {
+    key: '4',
+    name: 'XiaoMing',
+    age: 30,
+    address: 'BeiJing No.5 High School',
+  },
 ];
 
-stories.add('sort table', () => <Table columns={sortColumns} dataSource={sortData}/>);
-stories.add('controlled sortOrder table', () => <ControlledSortOrder/>);
-
-stories.add('middle table', () => <Table columns={columns} dataSource={data} size="middle"/>);
-
-stories.add('small table', () => <Table columns={columns} dataSource={data} size="small"/>);
-
-stories.add('expand table', () => <ExpandDemo/>);
-
-stories.add('resizable columns', () => <ResizableColumns/>);
-
-stories.add('dragable table', () => <DragableTableDemo/>);
-stories.add('fixed table', () => <FixedTable/>);
-stories.add('fixed jsx table', () => <JSXFixedTable/>);
-stories.add(`fixed expanded rows`, () => <FixedExpandedRows/>);
-
-stories.add(`jsx titles`, () => <JSXTitles/>);
-
-stories.add('dynamic table', () => (
-    <div style={{padding: 20}}>
-        <DynamicTableDemo/>
-    </div>
-));
-
-stories.add('linked scroll', () => <LinkedScroll/>);
-
-stories.add('modal table', () => <ModalTable/>);
-
-stories.add('tabs table', () => <TabsTable/>);
-
-stories.add('event table', () => <EventTable/>);
-
-stories.add('fn table', () => <FnTable/>);
-
-stories.add('dynamic filters', () => <DynamicFilters/>);
-
-stories.add('resizable table', () => <ResizableTable/>);
-
-stories.add('with pagination', () => <PaginationDemo/>);
-stories.add(`controlled pagination`, () => <ControlledPagination/>);
-
-stories.add('selected rows', () => <SelectedRowsDemo/>);
-
-stories.add('children data', () => <ChildrenData/>);
-
-stories.add('children data selected rows', () => <ChildrenDataSelected/>);
-stories.add(`with side sheet`, () => <WithSideSheet/>);
-stories.add(`in side sheet`, () => <InSideSheet/>);
-stories.add(`grouped rows`, () => <GroupedRows/>);
-stories.add(`grouped rows fixed`, () => <GroupedRowsFixed/>);
-stories.add(`grouped cols`, () => <GroupedCols/>);
-stories.add(`grouped cols fixed`, () => <GroupedColsFixed/>);
-stories.add(`grouped cols fixed jsx`, () => <GroupedColsFixedJSX/>);
-
-stories.add(`grouped cols fixed virtualized`, () => <GroupedColsFixedVirtualized/>);
-stories.add(`grouped cols fixed virtualized groups`, () => <GroupedColsFixedVirtualizedGroups/>);
-
-stories.add(`fixed groups`, () => <FixedGroups/>);
-stories.add(`custom components`, () => <CustomComponents/>);
-stories.add(`custom expand icons`, () => <CustomExpandIcons/>);
-stories.add(`custom filter dropdown item`, () => <CustomFilterDropdownItem/>);
-stories.add(`virtualized`, () => <VirtualizedDemo/>);
-stories.add(`virtualized fixed`, () => <VirtualizedFixedDemo/>);
-stories.add(`virtualized not fixed`, () => <VirtualizedNotFixedDemo/>);
-stories.add(`virtualized data selected`, () => <VirtualizedDataSelected/>);
-stories.add(`virtualized grouped rows`, () => <VirtualizedGroupedRows/>);
-stories.add(`virtualized dynamic data`, () => <VirtualizedDynamicData/>);
-stories.add(`infinite scroll`, () => <InfiniteScroll/>);
-stories.add(`massive columns`, () => <MassiveColumns/>);
-stories.add(`full render`, () => <FulldRenderDemo/>);
-stories.add(`VirtualTableOnCell`, () => <VirtualTableOnCell/>);
-stories.add(`Perf Virtualized`, () => <PerfVirtualized/>);
-stories.add(`Perf Render`, () => <PerfRender/>);
-stories.add(`Perf Complex Render`, () => <PerfComplexRender/>);
-stories.add(`Perf Controlled Selection`, () => <ControlledSelection/>);
-stories.add(`Perf Context`, () => <PerfContext/>);
-stories.add(`Perf Resizable Selection`, () => <PerfResizableSelection/>);
-stories.add(`Perf Render Row Times`, () => <PerfOnRow/>);
-stories.add(`renderPagination`, () => <RenderPagination/>);
-stories.add(`RTL align scroll bar`, () => <RTLAlignScrollBar/>);
-stories.add(`JSX aysnc data`, () => <JSXAsyncData/>);
-stories.add(`JSX column and prop clumns`, () => <JSXColumnPropColumn/>);
-stories.add(`scroll bar`, () => <ScrollBar/>);
-stories.add(`fix table rowSpan/colSpan`, () => <TableSpan/>);
-stories.add(`fix column render return props #1373`, () => <FixRenderReturnProps/>);
-stories.add('expandAllRows', () => <ExpandAllRows/>);
-stories.add('expandAllGroupRows', () => <ExpandAllGroupRows/>);
-stories.add('expandRowByClick', () => <ExpandRowByClick/>);
-stories.add('rowSelection boolean', () => <Table columns={columns} dataSource={data} rowSelection/>);
-stories.add('fix all columns without width', () => <FixAllColumnsWithoutWidth />);
+export const SortTable = () => <Table columns={sortColumns} dataSource={sortData} />;
+
+SortTable.story = {
+  name: 'sort table',
+};
+
+export const ControlledSortOrderTable = () => <ControlledSortOrder />;
+
+ControlledSortOrderTable.story = {
+  name: 'controlled sortOrder table',
+};
+
+export const MiddleTable = () => <Table columns={columns} dataSource={data} size="middle" />;
+
+MiddleTable.story = {
+  name: 'middle table',
+};
+
+export const SmallTable = () => <Table columns={columns} dataSource={data} size="small" />;
+
+SmallTable.story = {
+  name: 'small table',
+};
+
+export const ExpandTable = () => <ExpandDemo />;
+
+ExpandTable.story = {
+  name: 'expand table',
+};
+
+export const _ResizableColumns = () => <ResizableColumns />;
+
+_ResizableColumns.story = {
+  name: 'resizable columns',
+};
+
+export const DragableTable = () => <DragableTableDemo />;
+
+DragableTable.story = {
+  name: 'dragable table',
+};
+DragableTable.parameters = {
+  chromatic: { disableSnapshot: true },
+}
+
+export const _FixedTable = () => <FixedTable />;
+
+_FixedTable.story = {
+  name: 'fixed table',
+};
+_FixedTable.parameters = {
+  chromatic: { disableSnapshot: true },
+}
+
+export const FixedJsxTable = () => <JSXFixedTable />;
+
+FixedJsxTable.story = {
+  name: 'fixed jsx table',
+};
+
+export const JSXTitlesDemo = () => <JSXTitles />;
+JSXTitlesDemo.story = {
+  name: 'jsx titles'
+};
+
+export const DynamicTable = () => (
+  <div style={{ padding: 20 }}>
+    <DynamicTableDemo />
+  </div>
+);
+
+DynamicTable.story = {
+  name: 'dynamic table',
+};
+
+export const _LinkedScroll = () => <LinkedScroll />;
+
+_LinkedScroll.story = {
+  name: 'linked scroll',
+};
+
+export const _ModalTable = () => <ModalTable />;
+
+_ModalTable.story = {
+  name: 'modal table',
+};
+
+export const _TabsTable = () => <TabsTable />;
+
+_TabsTable.story = {
+  name: 'tabs table',
+};
+
+export const _EventTable = () => <EventTable />;
+
+_EventTable.story = {
+  name: 'event table',
+};
+
+export const _FnTable = () => <FnTable />;
+
+_FnTable.story = {
+  name: 'fn table',
+};
+
+export const _DynamicFilters = () => <DynamicFilters />;
+
+_DynamicFilters.story = {
+  name: 'dynamic filters',
+};
+
+export const _ResizableTable = () => <ResizableTable />;
+
+_ResizableTable.story = {
+  name: 'resizable table',
+};
+
+export const WithPagination = () => <PaginationDemo />;
+
+WithPagination.story = {
+  name: 'with pagination',
+};
+
+export const SelectedRows = () => <SelectedRowsDemo />;
+
+SelectedRows.story = {
+  name: 'selected rows',
+};
+
+export const _ChildrenData = () => <ChildrenData />;
+
+_ChildrenData.story = {
+  name: 'children data',
+};
+
+export const ChildrenDataSelectedRows = () => <ChildrenDataSelected />;
+
+ChildrenDataSelectedRows.story = {
+  name: 'children data selected rows',
+};
+
+export const _ExpandAllRows = () => <ExpandAllRows />;
+
+_ExpandAllRows.story = {
+  name: 'expandAllRows',
+};
+
+export const _ExpandAllGroupRows = () => <ExpandAllGroupRows />;
+
+_ExpandAllGroupRows.story = {
+  name: 'expandAllGroupRows',
+};
+
+export const _ExpandRowByClick = () => <ExpandRowByClick />;
+
+_ExpandRowByClick.story = {
+  name: 'expandRowByClick',
+};
+
+export const RowSelectionBoolean = () => <Table columns={columns} dataSource={data} rowSelection />;
+
+RowSelectionBoolean.story = {
+  name: 'rowSelection boolean',
+};
+
+export const _FixAllColumnsWithoutWidth = () => <FixAllColumnsWithoutWidth />;
+
+_FixAllColumnsWithoutWidth.story = {
+  name: 'fix all columns without width',
+};
+
+export const JSXColumnPropColumnDemo = () => <JSXColumnPropColumn />;
+
+export const FixedExpandedRowsDemo = () => <FixedExpandedRows />;
+FixedExpandedRowsDemo.parameters = {
+  chromatic: { disableSnapshot: true },
+}
+
+export const CustomFilterDropdownItemDemo = () => <CustomFilterDropdownItem />;
+
+export const Virtualized = () => <VirtualizedDemo />;
+
+export const VirtualizedNotFixedDemo = () => <VirtualizedNotFixed />;
+
+export const InfiniteScrollDemo = () => <InfiniteScroll />;
+export const VirtualTableOnCellDemo = () => <VirtualTableOnCell />;
+export const ControlledSelectionDemo = () => <ControlledSelection />;
+ControlledSelectionDemo.parameters = {
+  chromatic: { disableSnapshot: true },
+}
+export const PerfComplexRenderDemo = () => <PerfComplexRender />;
+PerfComplexRenderDemo.parameters = {
+  chromatic: { disableSnapshot: true },
+}
+export const PerfContextDemo = () => <PerfContext />;
+export const PerfOnRowDemo = () => <PerfOnRow />;
+PerfOnRowDemo.parameters = {
+  chromatic: { disableSnapshot: true },
+}
+export const PerfResizableSelectionDemo = () => <PerfResizableSelection />;
+PerfResizableSelectionDemo.parameters = {
+  chromatic: { disableSnapshot: true },
+}
+export const PerfVirtualizedDemo = () => <PerfVirtualized />;
+export const PerfRenderDemo = () => <PerfRender />;
+PerfRenderDemo.parameters = {
+  chromatic: { disableSnapshot: true },
+}
+export const RenderPaginationDemo = () => <RenderPagination />;

+ 1 - 1
packages/semi-ui/table/_story/table.stories.tsx

@@ -102,7 +102,7 @@ stories.add(`header merge table`, () => {
     const data = useMemo(() => {
         const data = [];
         for (let i = 0; i < 100; i++) {
-            let age = 40 + (Math.random() > 0.5 ? 1 : -1) * (i % 9);
+            let age = (i * 1000) % 149 ;
             let name = `Edward King ${i}`;
             data.push({
                 key: '' + i,

+ 1 - 1
packages/semi-ui/table/_story/virtualized/index.js

@@ -52,7 +52,7 @@ class VirtualizedFixedDemo extends React.Component {
         };
 
         for (let i = 0; i < 10000; i++) {
-            let age = 40 + (Math.random() > 0.5 ? 1 : -1) * (i % 9);
+            let age = (i * 1000) % 149 ;
             let name = `Edward King ${i}`;
             this.data.push({
                 key: '' + i,

+ 730 - 653
packages/semi-ui/tabs/_story/tabs.stories.js

@@ -1,5 +1,4 @@
 import React, { useState } from 'react';
-import { storiesOf } from '@storybook/react';
 import Tabs from '../index';
 import Button from '@douyinfe/semi-ui/button/index';
 import Typography from '@douyinfe/semi-ui/typography/index';
@@ -9,712 +8,790 @@ import Icon from '../../icons';
 import { IconFile, IconGlobe, IconHelpCircle } from '@douyinfe/semi-icons';
 const TabPane = Tabs.TabPane;
 const { Title } = Typography;
-const stories = storiesOf('Tabs', module); // stories.addDecorator(withKnobs);;
+
+export default {
+  title: 'Tabs'
+}
 
 const style = {
-    width: '600px',
-    margin: '20px',
+  width: '600px',
+  margin: '20px',
 };
 
 const onChange = activeKey => {
-    console.log('onChange: activeKey =>', activeKey);
+  console.log('onChange: activeKey =>', activeKey);
 };
 
 const onTabClick = (activeKey, event) => {
-    console.log('onTabClick: onTabClick =>', activeKey);
+  console.log('onTabClick: onTabClick =>', activeKey);
 };
 
 const operations = (
-    <Button
-        onClick={() => {
-            alert('you have clicked me!');
-        }}
-    >
-        Extra Action
-    </Button>
+  <Button
+    onClick={() => {
+      alert('you have clicked me!');
+    }}
+  >
+    Extra Action
+  </Button>
 );
 
 class App extends React.Component {
-    render() {
-        return (
-            <div>
-                <Tabs type="line">
-                    <TabPane tab="文档" itemKey="1">
-                        <h3>文档</h3>
-                        <p
-                            style={{
-                                lineHeight: 1.8,
-                            }}
-                        >
-                            Semi Design 是由互娱社区前端团队与 UED
-                            团队共同设计开发并维护的设计系统。设计系统包含设计语言以及一整套可复用的前端组件,帮助设计师与开发者更容易地打造高质量的、用户体验一致的、符合设计规范的
-                            Web 应用。
-                        </p>
-                        <p
-                            style={{
-                                lineHeight: 1.8,
-                            }}
-                        >
-                            区别于其他的设计系统而言,Semi Design
-                            以用户中心、内容优先、设计人性化为设计理念,具有以下优势:
-                        </p>
-                        <ul>
-                            <li>
-                                <p>Semi Design 以内容优先进行设计。</p>
-                            </li>
-                            <li>
-                                <p>更容易地自定义主题。</p>
-                            </li>
-                            <li>
-                                <p>适用国际化场景。</p>
-                            </li>
-                            <li>
-                                <p>效率场景加入人性化关怀。</p>
-                            </li>
-                        </ul>
-                        <h3>文档</h3>
-                        <p
-                            style={{
-                                lineHeight: 1.8,
-                            }}
-                        >
-                            Semi Design 是由互娱社区前端团队与 UED
-                            团队共同设计开发并维护的设计系统。设计系统包含设计语言以及一整套可复用的前端组件,帮助设计师与开发者更容易地打造高质量的、用户体验一致的、符合设计规范的
-                            Web 应用。
-                        </p>
-                        <p
-                            style={{
-                                lineHeight: 1.8,
-                            }}
-                        >
-                            区别于其他的设计系统而言,Semi Design
-                            以用户中心、内容优先、设计人性化为设计理念,具有以下优势:
-                        </p>
-                        <ul>
-                            <li>
-                                <p>Semi Design 以内容优先进行设计。</p>
-                            </li>
-                            <li>
-                                <p>更容易地自定义主题。</p>
-                            </li>
-                            <li>
-                                <p>适用国际化场景。</p>
-                            </li>
-                            <li>
-                                <p>效率场景加入人性化关怀。</p>
-                            </li>
-                        </ul>
-                    </TabPane>
-                    <TabPane tab="快速起步" itemKey="2">
-                        <h3>快速起步</h3>
-                        <p
-                            style={{
-                                lineHeight: 1.8,
-                            }}
-                        >
-                            如果是全新的项目,建议你使用 eden 初始化项目,初始化项目类型选择 react
-                        </p>
-                        <pre
-                            style={{
-                                margin: '24px 0',
-                                padding: '20px',
-                                border: 'none',
-                                whiteSpace: 'normal',
-                                borderRadius: '6px',
-                                color: 'var(--semi-color-text-1)',
-                                backgroundColor: 'var(--semi-color-fill-0)',
-                            }}
-                        >
-                            <code>
-                                
-                            </code>
-                        </pre>
-                    </TabPane>
-                    <TabPane tab="帮助" itemKey="3">
-                        <h3>帮助</h3>
-                        <p
-                            style={{
-                                lineHeight: 1.8,
-                                color: 'var(--semi-color-text-0)',
-                                fontWeight: 600,
-                            }}
-                        >
-                            Q:有新组件需求、或者现有组件feature不能满足业务需求?
-                        </p>
-                        <p
-                            style={{
-                                lineHeight: 1.8,
-                                color: 'var(--semi-color-text-1)',
-                            }}
-                        >
-                            右上角问题反馈,提交issue,label选择Feature Request / New Component Request
-                            我们会高优处理这些需求。
-                        </p>
-                        <p
-                            style={{
-                                lineHeight: 1.8,
-                                color: 'var(--semi-color-text-0)',
-                                fontWeight: 600,
-                            }}
-                        >
-                            Q:对组件的使用有疑惑?
-                        </p>
-                        <p
-                            style={{
-                                lineHeight: 1.8,
-                                color: 'var(--semi-color-text-1)',
-                            }}
-                        >
-                            欢迎进我们的客服lark群进行咨询提问。
-                        </p>
-                    </TabPane>
-                </Tabs>
-            </div>
-        );
-    }
+  render() {
+    return (
+      <div>
+        <Tabs type="line">
+          <TabPane tab="文档" itemKey="1">
+            <h3>文档</h3>
+            <p
+              style={{
+                lineHeight: 1.8,
+              }}
+            >
+              Semi Design 是由互娱社区前端团队与 UED
+              团队共同设计开发并维护的设计系统。设计系统包含设计语言以及一整套可复用的前端组件,帮助设计师与开发者更容易地打造高质量的、用户体验一致的、符合设计规范的
+              Web 应用。
+            </p>
+            <p
+              style={{
+                lineHeight: 1.8,
+              }}
+            >
+              区别于其他的设计系统而言,Semi Design
+              以用户中心、内容优先、设计人性化为设计理念,具有以下优势:
+            </p>
+            <ul>
+              <li>
+                <p>Semi Design 以内容优先进行设计。</p>
+              </li>
+              <li>
+                <p>更容易地自定义主题。</p>
+              </li>
+              <li>
+                <p>适用国际化场景。</p>
+              </li>
+              <li>
+                <p>效率场景加入人性化关怀。</p>
+              </li>
+            </ul>
+            <h3>文档</h3>
+            <p
+              style={{
+                lineHeight: 1.8,
+              }}
+            >
+              Semi Design 是由互娱社区前端团队与 UED
+              团队共同设计开发并维护的设计系统。设计系统包含设计语言以及一整套可复用的前端组件,帮助设计师与开发者更容易地打造高质量的、用户体验一致的、符合设计规范的
+              Web 应用。
+            </p>
+            <p
+              style={{
+                lineHeight: 1.8,
+              }}
+            >
+              区别于其他的设计系统而言,Semi Design
+              以用户中心、内容优先、设计人性化为设计理念,具有以下优势:
+            </p>
+            <ul>
+              <li>
+                <p>Semi Design 以内容优先进行设计。</p>
+              </li>
+              <li>
+                <p>更容易地自定义主题。</p>
+              </li>
+              <li>
+                <p>适用国际化场景。</p>
+              </li>
+              <li>
+                <p>效率场景加入人性化关怀。</p>
+              </li>
+            </ul>
+          </TabPane>
+          <TabPane tab="快速起步" itemKey="2">
+            <h3>快速起步</h3>
+            <p
+              style={{
+                lineHeight: 1.8,
+              }}
+            >
+              如果是全新的项目,建议你使用 eden 初始化项目,初始化项目类型选择 react
+            </p>
+            <pre
+              style={{
+                margin: '24px 0',
+                padding: '20px',
+                border: 'none',
+                whiteSpace: 'normal',
+                borderRadius: '6px',
+                color: 'var(--semi-color-text-1)',
+                backgroundColor: 'var(--semi-color-fill-0)',
+              }}
+            >
+              <code></code>
+            </pre>
+          </TabPane>
+          <TabPane tab="帮助" itemKey="3">
+            <h3>帮助</h3>
+            <p
+              style={{
+                lineHeight: 1.8,
+                color: 'var(--semi-color-text-0)',
+                fontWeight: 600,
+              }}
+            >
+              Q:有新组件需求、或者现有组件feature不能满足业务需求?
+            </p>
+            <p
+              style={{
+                lineHeight: 1.8,
+                color: 'var(--semi-color-text-1)',
+              }}
+            >
+              右上角问题反馈,提交issue,label选择Feature Request / New Component Request
+              我们会高优处理这些需求。
+            </p>
+            <p
+              style={{
+                lineHeight: 1.8,
+                color: 'var(--semi-color-text-0)',
+                fontWeight: 600,
+              }}
+            >
+              Q:对组件的使用有疑惑?
+            </p>
+            <p
+              style={{
+                lineHeight: 1.8,
+                color: 'var(--semi-color-text-1)',
+              }}
+            >
+              欢迎进我们的客服lark群进行咨询提问。
+            </p>
+          </TabPane>
+        </Tabs>
+      </div>
+    );
+  }
 }
 
-stories.add('Level 1-无图标', () => (
-    <div
-        style={{
-            width: 500,
-            height: 500,
-            margin: 50,
-        }}
+export const Level1NoIcon = () => (
+  <div
+    style={{
+      width: 500,
+      height: 500,
+      margin: 50,
+    }}
+  >
+    <App />
+  </div>
+);
+
+Level1NoIcon.story = {
+  name: 'Level 1-无图标',
+};
+
+export const DefaultActiveKeyDemo = () => (
+  <Tabs style={style} defaultActiveKey="3" onChange={onChange} onTabClick={onTabClick}>
+    <TabPane tab="文档" itemKey="1">
+      <span>文档</span>
+    </TabPane>
+    <TabPane tab="快速起步" itemKey="2">
+      快速起步
+    </TabPane>
+    <TabPane tab="帮助" itemKey="3">
+      帮助
+    </TabPane>
+    <TabPane tab="关于" itemKey="4">
+      关于
+    </TabPane>
+    <TabPane tab="资源工具" itemKey="5">
+      资源工具
+    </TabPane>
+  </Tabs>
+);
+
+DefaultActiveKeyDemo.story = {
+  name: '指定defaultActiveKey',
+};
+
+export const Level1WithIcon = () => (
+  <Tabs style={style} defaultActiveKey="1" onChange={onChange} onTabClick={onTabClick}>
+    <TabPane
+      tab={
+        <span>
+          <IconFile />
+          文档
+        </span>
+      }
+      itemKey="1"
     >
-        <App />
-    </div>
-));
-stories.add('指定defaultActiveKey', () => (
-    <Tabs style={style} defaultActiveKey="3" onChange={onChange} onTabClick={onTabClick}>
-        <TabPane tab="文档" itemKey="1">
-            <span>文档</span>
-        </TabPane>
-        <TabPane tab="快速起步" itemKey="2">
-            快速起步
-        </TabPane>
-        <TabPane tab="帮助" itemKey="3">
-            帮助
-        </TabPane>
-        <TabPane tab="关于" itemKey="4">
-            关于
-        </TabPane>
-        <TabPane tab="资源工具" itemKey="5">
-            资源工具
-        </TabPane>
-    </Tabs>
-));
-stories.add('Level 1-有图标', () => (
-    <Tabs style={style} defaultActiveKey="1" onChange={onChange} onTabClick={onTabClick}>
-        <TabPane
-            tab={
-                <span>
-                    <IconFile />
-                    文档
-                </span>
-            }
-            itemKey="1"
-        >
-            文档
-        </TabPane>
-        <TabPane
-            tab={
-                <span>
-                    <IconGlobe />
-                    快速起步
-                </span>
-            }
-            itemKey="2"
-        >
-            快速起步
-        </TabPane>
-        <TabPane
-            tab={
-                <span>
-                    <IconHelpCircle />
-                    帮助
-                </span>
-            }
-            itemKey="3"
-        >
-            帮助
-        </TabPane>
-    </Tabs>
-));
-stories.add('Level 1-导航内容扩展', () => (
-    <Tabs style={style} defaultActiveKey="1" tabBarExtraContent={operations}>
-        <TabPane tab="文档" itemKey="1">
-            文档
-        </TabPane>
-        <TabPane tab="快速起步" itemKey="2">
-            快速起步
-        </TabPane>
-        <TabPane tab="帮助" itemKey="3">
-            帮助
-        </TabPane>
-        <TabPane tab="关于" itemKey="4">
-            关于
-        </TabPane>
-        <TabPane tab="资源工具" itemKey="5">
-            资源工具
-        </TabPane>
-    </Tabs>
-)); // Todo: Warning: Each child in a list should have a unique "itemKey" prop. why? 待解决。
+      文档
+    </TabPane>
+    <TabPane
+      tab={
+        <span>
+          <IconGlobe />
+          快速起步
+        </span>
+      }
+      itemKey="2"
+    >
+      快速起步
+    </TabPane>
+    <TabPane
+      tab={
+        <span>
+          <IconHelpCircle />
+          帮助
+        </span>
+      }
+      itemKey="3"
+    >
+      帮助
+    </TabPane>
+  </Tabs>
+);
 
-stories.add('Level 1-导航二次封装', () => (
-    <Tabs
+Level1WithIcon.story = {
+  name: 'Level 1-有图标',
+};
+
+export const Level1WithTabBarExtraContent = () => (
+  <Tabs style={style} defaultActiveKey="1" tabBarExtraContent={operations}>
+    <TabPane tab="文档" itemKey="1">
+      文档
+    </TabPane>
+    <TabPane tab="快速起步" itemKey="2">
+      快速起步
+    </TabPane>
+    <TabPane tab="帮助" itemKey="3">
+      帮助
+    </TabPane>
+    <TabPane tab="关于" itemKey="4">
+      关于
+    </TabPane>
+    <TabPane tab="资源工具" itemKey="5">
+      资源工具
+    </TabPane>
+  </Tabs>
+);
+
+Level1WithTabBarExtraContent.story = {
+  name: 'Level 1-导航内容扩展',
+};
+
+export const RenderTabBar = () => (
+  <Tabs
+    style={style}
+    defaultActiveKey="1"
+    renderTabBar={(tabBarProps, DefaultTabBar) => {
+      return (
+        <div className="tab-bar-box" itemKey="bar">
+          这是二次封装的Tab Bar,当前ActiveKey:{tabBarProps.activeKey}
+          <DefaultTabBar {...tabBarProps} />
+        </div>
+      );
+    }}
+  >
+    <TabPane tab="文档" itemKey="1">
+      文档
+    </TabPane>
+    <TabPane tab="快速起步" itemKey="2">
+      快速起步
+    </TabPane>
+    <TabPane tab="帮助" itemKey="3">
+      帮助
+    </TabPane>
+    <TabPane tab="关于" itemKey="4">
+      关于
+    </TabPane>
+    <TabPane tab="资源工具" itemKey="5">
+      资源工具
+    </TabPane>
+  </Tabs>
+);
+
+RenderTabBar.story = {
+  name: 'Level 1-导航二次封装',
+};
+
+export const DisabledTab = () => (
+  <Tabs style={style} defaultActiveKey="1">
+    <TabPane tab="文档" itemKey="1">
+      文档
+    </TabPane>
+    <TabPane tab="快速起步" itemKey="2">
+      快速起步
+    </TabPane>
+    <TabPane tab="帮助" itemKey="3" disabled>
+      帮助
+    </TabPane>
+    <TabPane tab="关于" itemKey="4" disabled>
+      关于
+    </TabPane>
+    <TabPane tab="资源工具" itemKey="5">
+      资源工具
+    </TabPane>
+  </Tabs>
+);
+
+DisabledTab.story = {
+  name: 'Level 1-不可点击Tab',
+};
+
+export const Level2Card = () => (
+  <Tabs style={style} defaultActiveKey="1" type="card">
+    <TabPane tab="文档" itemKey="1">
+      文档
+    </TabPane>
+    <TabPane tab="快速起步" itemKey="2">
+      快速起步
+    </TabPane>
+    <TabPane tab="帮助" itemKey="3">
+      帮助
+    </TabPane>
+    <TabPane tab="关于" itemKey="4">
+      关于
+    </TabPane>
+    <TabPane tab="资源工具" itemKey="5">
+      资源工具
+    </TabPane>
+  </Tabs>
+);
+
+Level2Card.story = {
+  name: 'Level 2-卡片Tab',
+};
+
+export const Level3ButtonTab = () => (
+  <Tabs style={style} defaultActiveKey="1" type="button">
+    <TabPane tab="文档" itemKey="1">
+      文档
+    </TabPane>
+    <TabPane tab="快速起步" itemKey="2">
+      快速起步
+    </TabPane>
+    <TabPane tab="帮助" itemKey="3">
+      帮助
+    </TabPane>
+    <TabPane tab="关于" itemKey="4">
+      关于
+    </TabPane>
+    <TabPane tab="资源工具" itemKey="5">
+      资源工具
+    </TabPane>
+  </Tabs>
+);
+
+Level3ButtonTab.story = {
+  name: 'Level 3-按钮Tab',
+};
+
+class TabDemo extends React.Component {
+  constructor() {
+    super();
+    this.state = {
+      itemKey: '1',
+    };
+    this.onTabClick = this.onTabClick.bind(this);
+  }
+
+  onTabClick(itemKey, type) {
+    this.setState({
+      [type]: itemKey,
+    });
+  }
+
+  render() {
+    const contentList = [
+      <div>文档</div>,
+      <div>快速起步</div>,
+      <div>帮助</div>,
+      <div>关于</div>,
+      <div>资源工具</div>,
+    ];
+    const tabList = [
+      {
+        tab: '文档',
+        itemKey: '1',
+      },
+      {
+        tab: '快速起步',
+        itemKey: '2',
+      },
+      {
+        tab: '帮助',
+        itemKey: '3',
+      },
+      {
+        tab: '关于',
+        itemKey: '4',
+      },
+      {
+        tab: '资源工具',
+        itemKey: '5',
+      },
+    ];
+    return (
+      <Tabs
         style={style}
-        defaultActiveKey="1"
-        renderTabBar={(tabBarProps, DefaultTabBar) => {
-            return (
-                <div className="tab-bar-box" itemKey="bar">
-                    这是二次封装的Tab Bar,当前ActiveKey:{tabBarProps.activeKey}
-                    <DefaultTabBar {...tabBarProps} />
-                </div>
-            );
+        type="line"
+        tabList={tabList}
+        onTabClick={itemKey => {
+          this.onTabClick(itemKey, 'itemKey');
         }}
-    >
+      >
+        {contentList[this.state.itemKey]}
+        <span>test</span>
+        <span>test2</span>
+      </Tabs>
+    );
+  }
+}
+
+export const TabList = () => <TabDemo />;
+
+TabList.story = {
+  name: 'tabList',
+};
+
+class TabDemo2 extends React.Component {
+  constructor() {
+    super();
+    this.state = {
+      key: '1',
+    };
+    this.onTabClick = this.onTabClick.bind(this);
+  }
+
+  onTabClick(val) {
+    console.log('key', val);
+    this.setState({
+      key: val,
+    });
+  }
+
+  render() {
+    return (
+      <Tabs type="line" activeKey={this.state.key} onChange={val => this.onTabClick(val)}>
         <TabPane tab="文档" itemKey="1">
-            文档
+          文档
         </TabPane>
         <TabPane tab="快速起步" itemKey="2">
-            快速起步
+          快速起步
         </TabPane>
         <TabPane tab="帮助" itemKey="3">
-            帮助
+          帮助
         </TabPane>
         <TabPane tab="关于" itemKey="4">
-            关于
-        </TabPane>
-        <TabPane tab="资源工具" itemKey="5">
-            资源工具
-        </TabPane>
-    </Tabs>
-));
-stories.add('Level 1-不可点击Tab', () => (
-    <Tabs style={style} defaultActiveKey="1">
-        <TabPane tab="文档" itemKey="1">
-            文档
-        </TabPane>
-        <TabPane tab="快速起步" itemKey="2">
-            快速起步
-        </TabPane>
-        <TabPane tab="帮助" itemKey="3" disabled>
-            帮助
-        </TabPane>
-        <TabPane tab="关于" itemKey="4" disabled>
-            关于
+          关于
         </TabPane>
         <TabPane tab="资源工具" itemKey="5">
-            资源工具
+          资源工具
         </TabPane>
-    </Tabs>
-));
-stories.add('Level 2-卡片Tab', () => (
-    <Tabs style={style} defaultActiveKey="1" type="card">
+      </Tabs>
+    );
+  }
+}
+
+export const ActiveKey = () => <TabDemo2 />;
+
+ActiveKey.story = {
+  name: 'activeKey',
+};
+
+class TabDemo3 extends React.Component {
+  constructor() {
+    super();
+    this.state = {
+      key: '1',
+      type: 'here',
+    };
+  }
+
+  onTabClick(val) {
+    console.log('key', val);
+    this.setState({
+      key: val,
+      type: 'search',
+    });
+  }
+
+  render() {
+    let type = this.state.type;
+    return (
+      <Tabs type="line" activeKey={this.state.key} onChange={val => this.onTabClick(val)}>
         <TabPane tab="文档" itemKey="1">
-            文档
+          文档
         </TabPane>
         <TabPane tab="快速起步" itemKey="2">
-            快速起步
-        </TabPane>
-        <TabPane tab="帮助" itemKey="3">
-            帮助
-        </TabPane>
-        <TabPane tab="关于" itemKey="4">
-            关于
-        </TabPane>
-        <TabPane tab="资源工具" itemKey="5">
-            资源工具
-        </TabPane>
-    </Tabs>
-));
-stories.add('Level 3-按钮Tab', () => (
-    <Tabs style={style} defaultActiveKey="1" type="button">
-        <TabPane tab="文档" itemKey="1">
+          快速起步
+        </TabPane>
+        {type === 'search' && (
+          <TabPane tab="搜索" itemKey="3">
+            搜索
+          </TabPane>
+        )}
+      </Tabs>
+    );
+  }
+}
+
+export const Dynamic = () => <TabDemo3 />;
+
+class TabDemo4 extends React.Component {
+  constructor() {
+    super();
+    this.state = {
+      loading: true,
+    };
+  }
+
+  updateTab = () => {
+    this.setState({
+      loading: !this.state.loading,
+    });
+    this.tab = Math.random();
+  };
+
+  render() {
+    let type = this.state.type;
+    return (
+      <div>
+        <Button onClick={() => this.updateTab()}>change</Button>
+        <Tabs type="line">
+          <TabPane tab={this.tab} itemKey="1">
             文档
-        </TabPane>
-        <TabPane tab="快速起步" itemKey="2">
+          </TabPane>
+          <TabPane tab="快速起步" itemKey="2">
             快速起步
-        </TabPane>
-        <TabPane tab="帮助" itemKey="3">
-            帮助
-        </TabPane>
-        <TabPane tab="关于" itemKey="4">
-            关于
-        </TabPane>
-        <TabPane tab="资源工具" itemKey="5">
-            资源工具
-        </TabPane>
-    </Tabs>
-));
-
-class TabDemo extends React.Component {
-    constructor() {
-        super();
-        this.state = {
-            itemKey: '1',
-        };
-        this.onTabClick = this.onTabClick.bind(this);
-    }
-
-    onTabClick(itemKey, type) {
-        this.setState({
-            [type]: itemKey,
-        });
-    }
-
-    render() {
-        const contentList = [
-            <div>文档</div>,
-            <div>快速起步</div>,
-            <div>帮助</div>,
-            <div>关于</div>,
-            <div>资源工具</div>,
-        ];
-        const tabList = [
-            {
-                tab: '文档',
-                itemKey: '1',
-            },
-            {
-                tab: '快速起步',
-                itemKey: '2',
-            },
-            {
-                tab: '帮助',
-                itemKey: '3',
-            },
-            {
-                tab: '关于',
-                itemKey: '4',
-            },
-            {
-                tab: '资源工具',
-                itemKey: '5',
-            },
-        ];
-        return (
-            <Tabs
-                style={style}
-                type="line"
-                tabList={tabList}
-                onTabClick={itemKey => {
-                    this.onTabClick(itemKey, 'itemKey');
-                }}
-            >
-                {contentList[this.state.itemKey]}
-                <span>test</span>
-                <span>test2</span>
-            </Tabs>
-        );
-    }
+          </TabPane>
+          {type === 'search' && (
+            <TabPane tab="搜索" itemKey="3">
+              搜索
+            </TabPane>
+          )}
+        </Tabs>
+      </div>
+    );
+  }
 }
 
-stories.add('tabList', () => <TabDemo />);
+export const Update = () => <TabDemo4 />;
 
-class TabDemo2 extends React.Component {
-    constructor() {
-        super();
-        this.state = {
-            key: '1',
-        };
-        this.onTabClick = this.onTabClick.bind(this);
-    }
-
-    onTabClick(val) {
-        console.log('key', val);
-        this.setState({
-            key: val,
-        });
-    }
-
-    render() {
-        return (
-            <Tabs type="line" activeKey={this.state.key} onChange={val => this.onTabClick(val)}>
-                <TabPane tab="文档" itemKey="1">
-                    文档
-                </TabPane>
-                <TabPane tab="快速起步" itemKey="2">
-                    快速起步
-                </TabPane>
-                <TabPane tab="帮助" itemKey="3">
-                    帮助
-                </TabPane>
-                <TabPane tab="关于" itemKey="4">
-                    关于
-                </TabPane>
-                <TabPane tab="资源工具" itemKey="5">
-                    资源工具
-                </TabPane>
-            </Tabs>
-        );
-    }
+export const RenderCurrentPane = () => (
+  <Tabs style={style} keepDOM={false}>
+    <TabPane tab="文档" itemKey="1">
+      <span>文档</span>
+    </TabPane>
+    <TabPane tab="快速起步" itemKey="2">
+      快速起步
+    </TabPane>
+    <TabPane tab="帮助" itemKey="3">
+      帮助
+    </TabPane>
+    <TabPane tab="关于" itemKey="4">
+      关于
+    </TabPane>
+    <TabPane tab="资源工具" itemKey="5">
+      资源工具
+    </TabPane>
+  </Tabs>
+);
+
+RenderCurrentPane.story = {
+  name: '只渲染当前pane'
 }
 
-stories.add('activeKey', () => <TabDemo2 />);
+export const LazyRender = () => (
+  <Tabs style={style} lazyRender>
+    <TabPane tab="文档" itemKey="1">
+      <span>文档</span>
+    </TabPane>
+    <TabPane tab="快速起步" itemKey="2">
+      快速起步
+    </TabPane>
+    <TabPane tab="帮助" itemKey="3">
+      帮助
+    </TabPane>
+    <TabPane tab="关于" itemKey="4">
+      关于
+    </TabPane>
+    <TabPane tab="资源工具" itemKey="5">
+      资源工具
+    </TabPane>
+  </Tabs>
+);
+LazyRender.story = {
+  name: '懒渲染'
+}
 
-class TabDemo3 extends React.Component {
-    constructor() {
-        super();
-        this.state = {
-            key: '1',
-            type: 'here',
-        };
-    }
-
-    onTabClick(val) {
-        console.log('key', val);
-        this.setState({
-            key: val,
-            type: 'search',
-        });
-    }
-
-    render() {
-        let type = this.state.type;
-        return (
-            <Tabs type="line" activeKey={this.state.key} onChange={val => this.onTabClick(val)}>
-                <TabPane tab="文档" itemKey="1">
-                    文档
-                </TabPane>
-                <TabPane tab="快速起步" itemKey="2">
-                    快速起步
-                </TabPane>
-                {type === 'search' && (
-                    <TabPane tab="搜索" itemKey="3">
-                        搜索
-                    </TabPane>
-                )}
-            </Tabs>
-        );
-    }
+export const VerticalTabs = () => (
+  <Tabs style={style} tabPosition="left">
+    <TabPane tab="文档" itemKey="1">
+      <span>文档</span>
+    </TabPane>
+    <TabPane tab="快速起步" itemKey="2">
+      快速起步
+    </TabPane>
+    <TabPane tab="帮助" itemKey="3">
+      帮助
+    </TabPane>
+    <TabPane tab="关于" itemKey="4">
+      关于
+    </TabPane>
+    <TabPane tab="资源工具" itemKey="5">
+      资源工具
+    </TabPane>
+  </Tabs>
+);
+VerticalTabs.story = {
+  name: '垂直的tabs'
 }
 
-stories.add('Dynamic', () => <TabDemo3 />);
+export const HorizontalTabs = () => (
+  <Tabs style={style} tabPosition="left" type="card">
+    <TabPane tab="文档" itemKey="1">
+      <span>文档</span>
+    </TabPane>
+    <TabPane tab="快速起步" itemKey="2">
+      快速起步
+    </TabPane>
+    <TabPane tab="帮助" itemKey="3">
+      帮助
+    </TabPane>
+    <TabPane tab="关于" itemKey="4">
+      关于
+    </TabPane>
+    <TabPane tab="资源工具" itemKey="5">
+      资源工具
+    </TabPane>
+  </Tabs>
+);
 
-class TabDemo4 extends React.Component {
-    constructor() {
-        super();
-        this.state = {
-            loading: true,
-        };
-    }
-
-    updateTab = () => {
-        this.setState({
-            loading: !this.state.loading,
-        });
-        this.tab = Math.random();
-    };
+HorizontalTabs.story = {
+  name: '垂直的tabs - 卡片',
+};
 
-    render() {
-        let type = this.state.type;
-        return (
-            <div>
-                <Button onClick={() => this.updateTab()}>change</Button>
-                <Tabs type="line">
-                    <TabPane tab={this.tab} itemKey="1">
-                        文档
-                    </TabPane>
-                    <TabPane tab="快速起步" itemKey="2">
-                        快速起步
-                    </TabPane>
-                    {type === 'search' && (
-                        <TabPane tab="搜索" itemKey="3">
-                            搜索
-                        </TabPane>
-                    )}
-                </Tabs>
-            </div>
-        );
-    }
-}
+export const VerticalTabsButton = () => (
+  <Tabs style={style} tabPosition="left" type="button">
+    <TabPane tab="文档" itemKey="1">
+      <span>文档</span>
+    </TabPane>
+    <TabPane tab="快速起步" itemKey="2">
+      快速起步
+    </TabPane>
+    <TabPane tab="帮助" itemKey="3">
+      帮助
+    </TabPane>
+    <TabPane tab="关于" itemKey="4">
+      关于
+    </TabPane>
+    <TabPane tab="资源工具" itemKey="5">
+      资源工具
+    </TabPane>
+  </Tabs>
+);
 
-stories.add('Update', () => <TabDemo4 />);
-stories.add('只渲染当前pane', () => (
-    <Tabs style={style} keepDOM={false}>
-        <TabPane tab="文档" itemKey="1">
-            <span>文档</span>
-        </TabPane>
-        <TabPane tab="快速起步" itemKey="2">
-            快速起步
-        </TabPane>
-        <TabPane tab="帮助" itemKey="3">
-            帮助
-        </TabPane>
-        <TabPane tab="关于" itemKey="4">
-            关于
-        </TabPane>
-        <TabPane tab="资源工具" itemKey="5">
-            资源工具
-        </TabPane>
-    </Tabs>
-));
-stories.add('懒渲染', () => (
-    <Tabs style={style} lazyRender>
-        <TabPane tab="文档" itemKey="1">
-            <span>文档</span>
-        </TabPane>
-        <TabPane tab="快速起步" itemKey="2">
-            快速起步
-        </TabPane>
-        <TabPane tab="帮助" itemKey="3">
-            帮助
-        </TabPane>
-        <TabPane tab="关于" itemKey="4">
-            关于
-        </TabPane>
-        <TabPane tab="资源工具" itemKey="5">
-            资源工具
-        </TabPane>
-    </Tabs>
-));
-stories.add('垂直的tabs', () => (
-    <Tabs style={style} tabPosition="left">
-        <TabPane tab="文档" itemKey="1">
-            <span>文档</span>
-        </TabPane>
-        <TabPane tab="快速起步" itemKey="2">
-            快速起步
-        </TabPane>
-        <TabPane tab="帮助" itemKey="3">
-            帮助
-        </TabPane>
-        <TabPane tab="关于" itemKey="4">
-            关于
-        </TabPane>
-        <TabPane tab="资源工具" itemKey="5">
-            资源工具
+VerticalTabsButton.story = {
+  name: '垂直的tabs - 按钮',
+};
+
+export const CollapseTabs = () => (
+  <div>
+    <Tabs
+      style={{
+        width: '60%',
+        margin: '20px',
+      }}
+      type="card"
+      collapsible
+    >
+      {[...Array(30).keys()].map(i => (
+        <TabPane tab={`Tab-${i}`} itemKey={`Tab-${i}`}>
+          Content of card tab {i}
         </TabPane>
+      ))}
     </Tabs>
-));
-stories.add('垂直的tabs - 卡片', () => (
-    <Tabs style={style} tabPosition="left" type="card">
-        <TabPane tab="文档" itemKey="1">
-            <span>文档</span>
-        </TabPane>
-        <TabPane tab="快速起步" itemKey="2">
-            快速起步
-        </TabPane>
-        <TabPane tab="帮助" itemKey="3">
-            帮助
-        </TabPane>
-        <TabPane tab="关于" itemKey="4">
-            关于
-        </TabPane>
-        <TabPane tab="资源工具" itemKey="5">
-            资源工具
-        </TabPane>
+    <br />
+    <br />
+    <Tabs style={style} type="button" collapsible>
+      {[...Array(30).keys()].map(i => (
+        <TabPane tab={`Tab-${i}`} itemKey={`${i}`}>
+          Content of button tab {i}
+        </TabPane>
+      ))}
     </Tabs>
-));
-stories.add('垂直的tabs - 按钮', () => (
-    <Tabs style={style} tabPosition="left" type="button">
-        <TabPane tab="文档" itemKey="1">
-            <span>文档</span>
-        </TabPane>
-        <TabPane tab="快速起步" itemKey="2">
-            快速起步
-        </TabPane>
-        <TabPane tab="帮助" itemKey="3">
-            帮助
-        </TabPane>
-        <TabPane tab="关于" itemKey="4">
-            关于
-        </TabPane>
-        <TabPane tab="资源工具" itemKey="5">
-            资源工具
-        </TabPane>
+    <br />
+    <br />
+    <Tabs style={style} type="line" collapsible>
+      {[...Array(30).keys()].map(i => (
+        <TabPane tab={`Tab-${i}`} itemKey={`${i}`}>
+          Content of line tab {i}
+        </TabPane>
+      ))}
     </Tabs>
-));
-stories.add('折叠的tabs', () => (
+  </div>
+);
+CollapseTabs.story = {
+  name: '折叠的tabs'
+}
+
+const TabSizeDemo = () => {
+  const typeList = ['line'];
+  const [size, setSize] = useState('large');
+  const [vertical, setVertical] = useState(false);
+  return (
     <div>
-        <Tabs
+      <RadioGroup onChange={e => setSize(e.target.value)} value={size}>
+        <Radio value={'small'}>small</Radio>
+        <Radio value={'medium'}>medium</Radio>
+        <Radio value={'large'}>large</Radio>
+      </RadioGroup>
+      <div
+        style={{
+          display: 'flex',
+          alignItems: 'center',
+        }}
+      >
+        <Title
+          heading={6}
+          style={{
+            margin: 8,
+          }}
+        >
+          {vertical ? '垂直' : '水平'}
+        </Title>
+        <Switch checked={vertical} onChange={setVertical} />
+      </div>
+      {typeList.map((type, index) => {
+        return (
+          <Tabs
             style={{
-                width: '60%',
-                margin: '20px',
+              width: '60%',
+              margin: '20px',
             }}
-            type="card"
-            collapsible
-        >
-            {[...Array(30).keys()].map(i => (
-                <TabPane tab={`Tab-${i}`} itemKey={`Tab-${i}`}>
-                    Content of card tab {i}
-                </TabPane>
-            ))}
-        </Tabs>
-        <br />
-        <br />
-        <Tabs style={style} type="button" collapsible>
-            {[...Array(30).keys()].map(i => (
-                <TabPane tab={`Tab-${i}`} itemKey={`${i}`}>
-                    Content of button tab {i}
-                </TabPane>
+            type={type}
+            size={size}
+            key={index}
+            tabPosition={vertical ? 'left' : 'top'}
+          >
+            {[...Array(3).keys()].map(i => (
+              <TabPane tab={`Tab-${i}`} itemKey={`Tab-${i}`}>
+                Content of {type} tab {i}
+              </TabPane>
             ))}
-        </Tabs>
-        <br />
-        <br />
-        <Tabs style={style} type="line" collapsible>
-            {[...Array(30).keys()].map(i => (
-                <TabPane tab={`Tab-${i}`} itemKey={`${i}`}>
-                    Content of line tab {i}
-                </TabPane>
-            ))}
-        </Tabs>
+          </Tabs>
+        );
+      })}
+      <br />
+      <br />
     </div>
-));
-
-const TabSizeDemo = () => {
-    const typeList = ['line'];
-    const [size, setSize] = useState('large');
-    const [vertical, setVertical] = useState(false);
-    return (
-        <div>
-            <RadioGroup onChange={e => setSize(e.target.value)} value={size}>
-                <Radio value={'small'}>small</Radio>
-                <Radio value={'medium'}>medium</Radio>
-                <Radio value={'large'}>large</Radio>
-            </RadioGroup>
-            <div
-                style={{
-                    display: 'flex',
-                    alignItems: 'center',
-                }}
-            >
-                <Title
-                    heading={6}
-                    style={{
-                        margin: 8,
-                    }}
-                >
-                    {vertical ? '垂直' : '水平'}
-                </Title>
-                <Switch checked={vertical} onChange={setVertical} />
-            </div>
-            {typeList.map((type, index) => {
-                return (
-                    <Tabs
-                        style={{
-                            width: '60%',
-                            margin: '20px',
-                        }}
-                        type={type}
-                        size={size}
-                        key={index}
-                        tabPosition={vertical ? 'left' : 'top'}
-                    >
-                        {[...Array(3).keys()].map(i => (
-                            <TabPane tab={`Tab-${i}`} itemKey={`Tab-${i}`}>
-                                Content of {type} tab {i}
-                            </TabPane>
-                        ))}
-                    </Tabs>
-                );
-            })}
-            <br />
-            <br />
-        </div>
-    );
+  );
 };
 
-stories.add('tab size', () => <TabSizeDemo />);
+export const TabSize = () => <TabSizeDemo />;
+
+TabSize.story = {
+  name: 'tab size',
+};

+ 214 - 150
packages/semi-ui/tag/_story/tag.stories.js

@@ -1,170 +1,234 @@
 /* argus-disable unPkgSensitiveInfo */
 import React from 'react';
-import { storiesOf } from '@storybook/react';
-// import { withKnobs, text } from '@storybook/addon-knobs';
 import withPropsCombinations from 'react-storybook-addon-props-combinations';
 import { BASE_CLASS_PREFIX } from '../../../semi-foundation/base/constants';
 
 import { Tag, TagGroup } from '../../index';
 
-const stories = storiesOf('Tag', module);
+export default {
+  title: 'Tag'
+}
 
-// stories.addDecorator(withKnobs);;
+export const Tag1 = () => (
+  <div>
+    <Tag>hello Tag</Tag>
+    <Tag>
+      <div>
+        leftBottom
+        <br />
+        leftBottom line 2
+      </div>
+    </Tag>
+  </div>
+);
+
+Tag1.story = {
+  name: 'tag 1',
+};
 
-stories.add('tag 1', () => (
-    <div>
-        <Tag>hello Tag</Tag>
-        <Tag>
-            <div>
-                leftBottom
-                <br />
-                leftBottom line 2
-            </div>
-        </Tag>
+export const Tag2 = () => (
+  <div>
+    <div className={`${BASE_CLASS_PREFIX}-tag-group`}>
+      <Tag color="red" closable>
+        hello Tag
+      </Tag>
+      <Tag color="red">hello Tag</Tag>
+      <Tag color="red">hello Tag</Tag>
+      <Tag color="red">hello Tag</Tag>
+      <Tag color="red">hello Tag</Tag>
+    </div>
+    <div className={`${BASE_CLASS_PREFIX}-tag-group`}>
+      <Tag color="green">hello Tag</Tag>
+      <Tag color="green">hello Tag</Tag>
+      <Tag color="green">hello Tag</Tag>
+      <Tag color="green">hello Tag</Tag>
+      <Tag color="green">hello Tag</Tag>
+    </div>
+    <div className={`${BASE_CLASS_PREFIX}-tag-group`}>
+      <Tag color="blue">hello Tag</Tag>
+      <Tag color="blue">hello Tag</Tag>
+      <Tag color="blue">hello Tag</Tag>
+      <Tag color="blue">hello Tag</Tag>
+      <Tag color="blue">hello Tag</Tag>
+    </div>
+    <div className={`${BASE_CLASS_PREFIX}-tag-group`}>
+      <Tag color="grey">hello Tag</Tag>
+      <Tag color="grey">hello Tag</Tag>
+      <Tag color="grey">hello Tag</Tag>
+      <Tag color="grey">hello Tag</Tag>
+      <Tag color="grey">hello Tag</Tag>
     </div>
-));
-
-stories.add('tag 2', () => (
-    <div>
-        <div className={`${BASE_CLASS_PREFIX}-tag-group`}>
-            <Tag color="red" closable>
-                hello Tag
-            </Tag>
-            <Tag color="red">hello Tag</Tag>
-            <Tag color="red">hello Tag</Tag>
-            <Tag color="red">hello Tag</Tag>
-            <Tag color="red">hello Tag</Tag>
-        </div>
-        <div className={`${BASE_CLASS_PREFIX}-tag-group`}>
-            <Tag color="green">hello Tag</Tag>
-            <Tag color="green">hello Tag</Tag>
-            <Tag color="green">hello Tag</Tag>
-            <Tag color="green">hello Tag</Tag>
-            <Tag color="green">hello Tag</Tag>
-        </div>
-        <div className={`${BASE_CLASS_PREFIX}-tag-group`}>
-            <Tag color="blue">hello Tag</Tag>
-            <Tag color="blue">hello Tag</Tag>
-            <Tag color="blue">hello Tag</Tag>
-            <Tag color="blue">hello Tag</Tag>
-            <Tag color="blue">hello Tag</Tag>
-        </div>
-        <div className={`${BASE_CLASS_PREFIX}-tag-group`}>
-            <Tag color="grey">hello Tag</Tag>
-            <Tag color="grey">hello Tag</Tag>
-            <Tag color="grey">hello Tag</Tag>
-            <Tag color="grey">hello Tag</Tag>
-            <Tag color="grey">hello Tag</Tag>
-        </div>
-        <div className={`${BASE_CLASS_PREFIX}-tag-group`}>
-            <Tag color="orange">hello Tag</Tag>
-            <Tag color="orange">hello Tag</Tag>
-            <Tag color="orange">hello Tag</Tag>
-            <Tag color="orange">hello Tag</Tag>
-            <Tag color="orange">hello Tag</Tag>
-        </div>
-        <div className={`${BASE_CLASS_PREFIX}-tag-group`}>
-            <Tag color="white">hello Tag</Tag>
-            <Tag color="white">hello Tag</Tag>
-            <Tag color="white">hello Tag</Tag>
-            <Tag color="white">hello Tag</Tag>
-            <Tag color="white">hello Tag</Tag>
-        </div>
+    <div className={`${BASE_CLASS_PREFIX}-tag-group`}>
+      <Tag color="orange">hello Tag</Tag>
+      <Tag color="orange">hello Tag</Tag>
+      <Tag color="orange">hello Tag</Tag>
+      <Tag color="orange">hello Tag</Tag>
+      <Tag color="orange">hello Tag</Tag>
     </div>
-));
-
-stories.add(
-    'combination show',
-    withPropsCombinations(
-        Tag,
-        {
-            children: ['hello Tag'],
-            size: ['large', 'small'],
-            closable: [true, false],
-            color: ['green', 'orange', 'blue', 'grey', 'red', 'white'],
-        },
-        {
-            showSource: false,
-        }
-    )
+    <div className={`${BASE_CLASS_PREFIX}-tag-group`}>
+      <Tag color="white">hello Tag</Tag>
+      <Tag color="white">hello Tag</Tag>
+      <Tag color="white">hello Tag</Tag>
+      <Tag color="white">hello Tag</Tag>
+      <Tag color="white">hello Tag</Tag>
+    </div>
+  </div>
+);
+
+Tag2.story = {
+  name: 'tag 2',
+};
+
+export const CombinationShow = withPropsCombinations(
+  Tag,
+  {
+    children: ['hello Tag'],
+    size: ['large', 'small'],
+    closable: [true, false],
+    color: ['green', 'orange', 'blue', 'grey', 'red', 'white'],
+  },
+  {
+    showSource: false,
+  }
 );
 
+CombinationShow.story = {
+  name: 'combination show',
+};
+
 const TagGroupDemo = () => {
-    let tagList = [
-        { color: 'white', children: '抖音' },
-        { color: 'white', children: '火山小视频' },
-        { color: 'white', children: 'Abc' },
-        { color: 'white', children: 'vigo' },
-        { color: 'white', children: '皮皮虾' },
-    ];
-    let divStyle = {
-        backgroundColor: 'var(--semi-color-fill-0)',
-        height: 35,
-        width: 300,
-        display: 'flex',
-        alignItems: 'center',
-        padding: '0 10px',
-    };
-    return (
-        <>
-            <div style={divStyle}>
-                <TagGroup maxTagCount={3} style={{ width: 300 }} tagList={tagList} size="large" showPopover></TagGroup>
-            </div>
-            <br/>
-            <div style={divStyle}>
-                <TagGroup maxTagCount={3} style={{ width: 300 }} tagList={tagList} size="small" showPopover></TagGroup>
-            </div>
-            <br/>
-            <div>
-                <TagGroup style={{ width: 300 }} tagList={tagList} size="large"></TagGroup>
-            </div>
-            <div>
-                <TagGroup style={{ width: 300 }} tagList={tagList} size="small"></TagGroup>
-            </div>
-        </>
-    );
+  let tagList = [
+    { color: 'white', children: '抖音' },
+    { color: 'white', children: '火山小视频' },
+    { color: 'white', children: 'Abc' },
+    { color: 'white', children: 'vigo' },
+    { color: 'white', children: '皮皮虾' },
+  ];
+  let divStyle = {
+    backgroundColor: 'var(--semi-color-fill-0)',
+    height: 35,
+    width: 300,
+    display: 'flex',
+    alignItems: 'center',
+    padding: '0 10px',
+  };
+  return (
+    <>
+      <div style={divStyle}>
+        <TagGroup
+          maxTagCount={3}
+          style={{ width: 300 }}
+          tagList={tagList}
+          size="large"
+          showPopover
+        ></TagGroup>
+      </div>
+      <br />
+      <div style={divStyle}>
+        <TagGroup
+          maxTagCount={3}
+          style={{ width: 300 }}
+          tagList={tagList}
+          size="small"
+          showPopover
+        ></TagGroup>
+      </div>
+      <br />
+      <div>
+        <TagGroup style={{ width: 300 }} tagList={tagList} size="large"></TagGroup>
+      </div>
+      <div>
+        <TagGroup style={{ width: 300 }} tagList={tagList} size="small"></TagGroup>
+      </div>
+    </>
+  );
+};
+
+export const _TagGroup = () => <TagGroupDemo />;
+
+_TagGroup.story = {
+  name: 'tagGroup',
 };
 
-stories.add('tagGroup', () => <TagGroupDemo />);
-
-stories.add('tag avatar', () => {
-    const avatarSrc = 'https://sf6-cdn-tos.douyinstatic.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/avatarDemo.jpeg';
-    return (
-        <div style={{ margin: 10 }}>
-            <Tag avatarSrc={avatarSrc} avatarShape={'square'}>李白</Tag><br />
-            <Tag avatarSrc={avatarSrc} avatarShape={'square'} size='large'>李白</Tag><br />
-            <Tag avatarSrc={avatarSrc} avatarShape={'circle'}>白居易</Tag><br />
-            <Tag avatarSrc={avatarSrc} avatarShape={'circle'} size='large'>白居易</Tag><br />
-            <Tag closable={true} avatarSrc={avatarSrc} avatarShape={'square'}>李白</Tag><br />
-            <Tag closable={true} avatarSrc={avatarSrc} avatarShape={'square'} size='large'>李白</Tag><br />
-            <Tag closable={true} avatarSrc={avatarSrc} avatarShape={'circle'}>白居易</Tag><br />
-            <Tag closable={true} avatarSrc={avatarSrc} avatarShape={'circle'} size='large'>白居易</Tag><br />
-        </div >
-    )
-});
+export const TagAvatar = () => {
+  const avatarSrc =
+    'https://sf6-cdn-tos.douyinstatic.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/avatarDemo.jpeg';
+  return (
+    <div style={{ margin: 10 }}>
+      <Tag avatarSrc={avatarSrc} avatarShape={'square'}>
+        李白
+      </Tag>
+      <br />
+      <Tag avatarSrc={avatarSrc} avatarShape={'square'} size="large">
+        李白
+      </Tag>
+      <br />
+      <Tag avatarSrc={avatarSrc} avatarShape={'circle'}>
+        白居易
+      </Tag>
+      <br />
+      <Tag avatarSrc={avatarSrc} avatarShape={'circle'} size="large">
+        白居易
+      </Tag>
+      <br />
+      <Tag closable={true} avatarSrc={avatarSrc} avatarShape={'square'}>
+        李白
+      </Tag>
+      <br />
+      <Tag closable={true} avatarSrc={avatarSrc} avatarShape={'square'} size="large">
+        李白
+      </Tag>
+      <br />
+      <Tag closable={true} avatarSrc={avatarSrc} avatarShape={'circle'}>
+        白居易
+      </Tag>
+      <br />
+      <Tag closable={true} avatarSrc={avatarSrc} avatarShape={'circle'} size="large">
+        白居易
+      </Tag>
+      <br />
+    </div>
+  );
+};
+
+TagAvatar.story = {
+  name: 'tag avatar',
+};
 
 const AvatarTagGroupDemo = () => {
-    const src = 'https://sf6-cdn-tos.douyinstatic.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/avatarDemo.jpeg';
-    let tagList = [
-        { color: 'white', children: '抖音', avatarSrc: src },
-        { color: 'white', children: '火山小视频', avatarSrc: src },
-        { color: 'white', children: 'Abc', avatarSrc: src },
-        { color: 'white', children: 'vigo', avatarSrc: src },
-        { color: 'white', children: '皮皮虾', avatarSrc: src },
-    ];
-    let divStyle = {
-        backgroundColor: 'var(--semi-color-fill-0)',
-        height: 35,
-        width: 350,
-        display: 'flex',
-        alignItems: 'center',
-        padding: '0 10px',
-    };
-    return (
-        <div style={divStyle}>
-            <TagGroup maxTagCount={3} style={{ width: 350 }} tagList={tagList} size="large" avatarShape='circle' showPopover></TagGroup>
-        </div>
-    );
+  const src =
+    'https://sf6-cdn-tos.douyinstatic.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/avatarDemo.jpeg';
+  let tagList = [
+    { color: 'white', children: '抖音', avatarSrc: src },
+    { color: 'white', children: '火山小视频', avatarSrc: src },
+    { color: 'white', children: 'Abc', avatarSrc: src },
+    { color: 'white', children: 'vigo', avatarSrc: src },
+    { color: 'white', children: '皮皮虾', avatarSrc: src },
+  ];
+  let divStyle = {
+    backgroundColor: 'var(--semi-color-fill-0)',
+    height: 35,
+    width: 350,
+    display: 'flex',
+    alignItems: 'center',
+    padding: '0 10px',
+  };
+  return (
+    <div style={divStyle}>
+      <TagGroup
+        maxTagCount={3}
+        style={{ width: 350 }}
+        tagList={tagList}
+        size="large"
+        avatarShape="circle"
+        showPopover
+      ></TagGroup>
+    </div>
+  );
 };
 
-stories.add('avatar tagGroup', () => <AvatarTagGroupDemo />);
+export const AvatarTagGroup = () => <AvatarTagGroupDemo />;
+
+AvatarTagGroup.story = {
+  name: 'avatar tagGroup',
+};

+ 391 - 320
packages/semi-ui/tagInput/_story/tagInput.stories.js

@@ -1,343 +1,414 @@
 import React from 'react';
-import { storiesOf } from '@storybook/react';
 import { Toast, Icon, Button, Avatar } from '@douyinfe/semi-ui/';
 import TagInput from '../index';
 import { IconGift, IconVigoLogo } from '@douyinfe/semi-icons';
-const stories = storiesOf('TagInput', module);
 const style = {
-    width: 400,
-    marginTop: 10,
+  width: 400,
+  marginTop: 10,
 };
-stories.add('default', () => (
-    <>
-    <TagInput defaultValue={['抖音', '火山', '西瓜视频']} placeholder='请输入...' style={style} />
-    <TagInput 
-        maxTagCount={2}
-        showRestTagsPopover={true}
-        restTagsPopoverProps={{ position: 'top' }}
-        defaultValue={['抖音','火山','西瓜视频']}
-        onChange={v => console.log(v)}
+
+export default {
+  title: 'TagInput'
+}
+
+export const Default = () => (
+  <>
+    <TagInput defaultValue={['抖音', '火山', '西瓜视频']} placeholder="请输入..." style={style} />
+    <TagInput
+      maxTagCount={2}
+      showRestTagsPopover={true}
+      restTagsPopoverProps={{ position: 'top' }}
+      defaultValue={['抖音', '火山', '西瓜视频']}
+      onChange={v => console.log(v)}
     />
-    </>
-))
-
-stories.add('autoFocus', () => (
-    <TagInput defaultValue={['抖音', '火山', '西瓜视频']} autoFocus placeholder='请输入...' style={style} />
-))
-
-
-stories.add('separator', () => (
-    <>
-        <TagInput
-            placeholder='默认 separator'
-            onChange={v => console.log(v)}
-        />
-        <br /><br />
-        <TagInput
-            separator='-'
-            placeholder='使用 - 进行批量输入'
-            onChange={v => console.log(v)}
-        />
-        <br /><br />
-        <TagInput
-            separator={[',','|','.']}
-            placeholder='支持多个分隔符进行批量输入'
-            onChange={v => console.log(v)}
-        />
-        <br /><br />
-        <TagInput
-            separator={null}
-            placeholder='separator 为 null'
-            onChange={v => console.log(v)}
-        />
-        <br /><br />
-        <TagInput
-            separator={1}
-            placeholder='separator 为 number'
-            onChange={v => console.log(v)}
-        />
-        <br /><br />
-        <TagInput
-            separator={' '}
-            placeholder='separator 为 空格'
-            onChange={v => console.log(v)}
-        />
-    </>
-))
-
-
-stories.add('showClear', () => (
-    <TagInput defaultValue={['抖音', '火山', '西瓜视频']} showClear style={style} />
-))
-
-stories.add('max / exceed', () => (
-    <>
-        <TagInput
-            style={style}
-            max={3}
-            placeholder="最多输入3条标签.."
-            onExceed={() => {
-                Toast.warning('不允许超过 max');
-            }}
-        />
-        <br />
-        <br />
-        <TagInput
-            style={style}
-            maxLength={5}
-            placeholder="单个标签长度不超过5..."
-            onInputExceed={() => {
-                Toast.warning('不允许超过 maxLength');
-            }}
-        />
-    </>
-));
-stories.add('size', () => (
-    <>
-        <TagInput style={style} size="small" showClear defaultValue={['抖音', '火山']} placeholder="请输入..." />
-        <br />
-        <br />
-        <TagInput style={style} showClear defaultValue={['抖音', '火山']} placeholder="请输入..." />
-        <br />
-        <br />
-        <TagInput style={style} size="large" showClear defaultValue={['抖音', '火山']} placeholder="请输入..." />
-    </>
-));
-stories.add('validateStatus', () => (
-    <>
-        <TagInput style={style} />
-        <br />
-        <br />
-        <TagInput style={style} validateStatus="default" />
-        <br />
-        <br />
-        <TagInput style={style} validateStatus="warning" />
-        <br />
-        <br />
-        <TagInput style={style} validateStatus="error" />
-    </>
-));
+  </>
+);
+
+Default.story = {
+  name: 'default',
+};
+
+export const AutoFocus = () => (
+  <TagInput
+    defaultValue={['抖音', '火山', '西瓜视频']}
+    autoFocus
+    placeholder="请输入..."
+    style={style}
+  />
+);
+
+AutoFocus.story = {
+  name: 'autoFocus',
+};
+
+export const Separator = () => (
+  <>
+    <TagInput placeholder="默认 separator" onChange={v => console.log(v)} />
+    <br />
+    <br />
+    <TagInput separator="-" placeholder="使用 - 进行批量输入" onChange={v => console.log(v)} />
+    <br />
+    <br />
+    <TagInput
+      separator={[',', '|', '.']}
+      placeholder="支持多个分隔符进行批量输入"
+      onChange={v => console.log(v)}
+    />
+    <br />
+    <br />
+    <TagInput separator={null} placeholder="separator 为 null" onChange={v => console.log(v)} />
+    <br />
+    <br />
+    <TagInput separator={1} placeholder="separator 为 number" onChange={v => console.log(v)} />
+    <br />
+    <br />
+    <TagInput separator={' '} placeholder="separator 为 空格" onChange={v => console.log(v)} />
+  </>
+);
+
+Separator.story = {
+  name: 'separator',
+};
+
+export const ShowClear = () => (
+  <TagInput defaultValue={['抖音', '火山', '西瓜视频']} showClear style={style} />
+);
+
+ShowClear.story = {
+  name: 'showClear',
+};
+
+export const MaxExceed = () => (
+  <>
+    <TagInput
+      style={style}
+      max={3}
+      placeholder="最多输入3条标签.."
+      onExceed={() => {
+        Toast.warning('不允许超过 max');
+      }}
+    />
+    <br />
+    <br />
+    <TagInput
+      style={style}
+      maxLength={5}
+      placeholder="单个标签长度不超过5..."
+      onInputExceed={() => {
+        Toast.warning('不允许超过 maxLength');
+      }}
+    />
+  </>
+);
+
+MaxExceed.story = {
+  name: 'max / exceed',
+};
+
+export const Size = () => (
+  <>
+    <TagInput
+      style={style}
+      size="small"
+      showClear
+      defaultValue={['抖音', '火山']}
+      placeholder="请输入..."
+    />
+    <br />
+    <br />
+    <TagInput style={style} showClear defaultValue={['抖音', '火山']} placeholder="请输入..." />
+    <br />
+    <br />
+    <TagInput
+      style={style}
+      size="large"
+      showClear
+      defaultValue={['抖音', '火山']}
+      placeholder="请输入..."
+    />
+  </>
+);
+
+Size.story = {
+  name: 'size',
+};
+
+export const ValidateStatus = () => (
+  <>
+    <TagInput style={style} />
+    <br />
+    <br />
+    <TagInput style={style} validateStatus="default" />
+    <br />
+    <br />
+    <TagInput style={style} validateStatus="warning" />
+    <br />
+    <br />
+    <TagInput style={style} validateStatus="error" />
+  </>
+);
+
+ValidateStatus.story = {
+  name: 'validateStatus',
+};
 
 class ChangeDemo extends React.Component {
-    constructor() {
-        super();
-        this.state = {
-            value: ['controlTag'],
-        };
-    }
-
-    onChange(value) {
-        this.setState({
-            value,
-        });
-    }
-
-    render() {
-        return (
-            <TagInput
-                style={style}
-                value={this.state.value}
-                onChange={value => {
-                    this.onChange(value);
-                }}
-            />
-        );
-    }
+  constructor() {
+    super();
+    this.state = {
+      value: ['controlTag'],
+    };
+  }
+
+  onChange(value) {
+    this.setState({
+      value,
+    });
+  }
+
+  render() {
+    return (
+      <TagInput
+        style={style}
+        value={this.state.value}
+        onChange={value => {
+          this.onChange(value);
+        }}
+      />
+    );
+  }
 }
 
-stories.add('value / onChange', () => <ChangeDemo />);
+export const ValueOnChange = () => <ChangeDemo />;
+
+ValueOnChange.story = {
+  name: 'value / onChange',
+};
 
 class InputChangeDemo extends React.Component {
-    constructor() {
-        super();
-        this.state = {
-            value: 'controlInput',
-        };
-    }
-
-    handleInputChange(value, event) {
-        this.setState({
-            value,
-        });
-    }
-
-    render() {
-        return (
-            <TagInput
-                style={style}
-                inputValue={this.state.value}
-                onInputChange={(v, e) => this.handleInputChange(v, e)}
-            />
-        );
-    }
+  constructor() {
+    super();
+    this.state = {
+      value: 'controlInput',
+    };
+  }
+
+  handleInputChange(value, event) {
+    this.setState({
+      value,
+    });
+  }
+
+  render() {
+    return (
+      <TagInput
+        style={style}
+        inputValue={this.state.value}
+        onInputChange={(v, e) => this.handleInputChange(v, e)}
+      />
+    );
+  }
 }
 
-stories.add('inputValue / onInputChange', () => <InputChangeDemo />);
-stories.add('onXXX', () => (
-    <>
-        <TagInput
-            style={style}
-            defaultValue={['抖音', '火山', '西瓜视频']}
-            placeholder="onFocus和onBlur"
-            showClear
-            onFocus={e => {
-                console.log(`onFocus`);
-            }}
-            onBlur={e => {
-                console.log(`onBlur`);
-            }}
-        />
-        <br />
-        <br />
-        <TagInput
-            style={style}
-            defaultValue={['抖音', '火山', '西瓜视频']}
-            placeholder="onChange"
-            showClear
-            onChange={tag => {
-                console.log(`onChange,当前标签数组:${tag}`);
-            }}
-        />
-        <br />
-        <br />
-        <TagInput
-            style={style}
-            defaultValue={['抖音', '火山', '西瓜视频']}
-            placeholder="onAdd和onRemove"
-            showClear
-            onAdd={tag => {
-                console.log(`onAdd,新增:${tag}`);
-            }}
-            onRemove={tag => {
-                console.log(`onRemove,移除: ${tag}`);
-            }}
-        />
-        <br />
-        <br />
-        <TagInput
-            style={style}
-            defaultValue={['抖音', '火山', '西瓜视频']}
-            placeholder="onInputChange"
-            showClear
-            onInputChange={(input, e) => {
-                console.log(`onInputChange,当前输入内容: ${input}`);
-            }}
-        />
-    </>
-));
-stories.add('disabled', () => (
-    <TagInput style={style} disabled showClear defaultValue={['抖音', '火山', '西瓜视频']} placeholder="请输入..." />
-));
+export const InputValueOnInputChange = () => <InputChangeDemo />;
+
+InputValueOnInputChange.story = {
+  name: 'inputValue / onInputChange',
+};
+
+export const OnXxx = () => (
+  <>
+    <TagInput
+      style={style}
+      defaultValue={['抖音', '火山', '西瓜视频']}
+      placeholder="onFocus和onBlur"
+      showClear
+      onFocus={e => {
+        console.log(`onFocus`);
+      }}
+      onBlur={e => {
+        console.log(`onBlur`);
+      }}
+    />
+    <br />
+    <br />
+    <TagInput
+      style={style}
+      defaultValue={['抖音', '火山', '西瓜视频']}
+      placeholder="onChange"
+      showClear
+      onChange={tag => {
+        console.log(`onChange,当前标签数组:${tag}`);
+      }}
+    />
+    <br />
+    <br />
+    <TagInput
+      style={style}
+      defaultValue={['抖音', '火山', '西瓜视频']}
+      placeholder="onAdd和onRemove"
+      showClear
+      onAdd={tag => {
+        console.log(`onAdd,新增:${tag}`);
+      }}
+      onRemove={tag => {
+        console.log(`onRemove,移除: ${tag}`);
+      }}
+    />
+    <br />
+    <br />
+    <TagInput
+      style={style}
+      defaultValue={['抖音', '火山', '西瓜视频']}
+      placeholder="onInputChange"
+      showClear
+      onInputChange={(input, e) => {
+        console.log(`onInputChange,当前输入内容: ${input}`);
+      }}
+    />
+  </>
+);
+
+OnXxx.story = {
+  name: 'onXXX',
+};
+
+export const Disabled = () => (
+  <TagInput
+    style={style}
+    disabled
+    showClear
+    defaultValue={['抖音', '火山', '西瓜视频']}
+    placeholder="请输入..."
+  />
+);
+
+Disabled.story = {
+  name: 'disabled',
+};
 
 class MethodsDemo extends React.Component {
-    constructor(props) {
-        super(props);
-        this.ref = React.createRef();
-        this.handleTagInputFocus = this.handleTagInputFocus.bind(this);
-    }
-
-    handleTagInputFocus() {
-        this.ref.current.focus();
-    }
-
-    render() {
-        return (
-            <>
-                <TagInput style={style} defaultValue={['抖音', '火山']} ref={this.ref} />
-                <br />
-                <Button
-                    style={{
-                        marginTop: 10,
-                    }}
-                    onClick={this.handleTagInputFocus}
-                >
-                    点击按钮聚焦
-                </Button>
-            </>
-        );
-    }
+  constructor(props) {
+    super(props);
+    this.ref = React.createRef();
+    this.handleTagInputFocus = this.handleTagInputFocus.bind(this);
+  }
+
+  handleTagInputFocus() {
+    this.ref.current.focus();
+  }
+
+  render() {
+    return (
+      <>
+        <TagInput style={style} defaultValue={['抖音', '火山']} ref={this.ref} />
+        <br />
+        <Button
+          style={{
+            marginTop: 10,
+          }}
+          onClick={this.handleTagInputFocus}
+        >
+          点击按钮聚焦
+        </Button>
+      </>
+    );
+  }
 }
 
-stories.add('focus() / blur()', () => <MethodsDemo />);
+export const FocusBlur = () => <MethodsDemo />;
+
+FocusBlur.story = {
+  name: 'focus() / blur()',
+};
 
 class CustomRender extends React.Component {
-    constructor() {
-        super();
-        this.state = {
-            list: [
-                {
-                    name: 'semi',
-                    email: '[email protected]',
-                    avatar:
-                        'https://sf6-cdn-tos.douyinstatic.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/bf8647bffab13c38772c9ff94bf91a9d.jpg',
-                },
-            ],
-        };
-    }
-
-    renderTagItem(node, index) {
-        return (
-            <div
-                key={index}
-                style={{
-                    display: 'flex',
-                    alignItems: 'center',
-                    fontSize: 14,
-                    marginRight: 10,
-                }}
-            >
-                <Avatar src={node.avatar} size="extra-small">
-                    {node.abbr}
-                </Avatar>
-                <span
-                    style={{
-                        marginLeft: 8,
-                    }}
-                >
-                    {node.email}
-                </span>
-            </div>
-        );
-    }
-
-    handleChange(value) {
-        const list = value.map(v => {
-            const item = {};
-            item.name = v.name || v;
-            item.email = `${item.name}@byte.com`;
-            item.avatar = `https://sf6-cdn-tos.douyinstatic.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/bf8647bffab13c38772c9ff94bf91a9d.jpg`;
-            return item;
-        });
-        this.setState({
-            list,
-        });
-    }
-
-    render() {
-        const { list } = this.state;
-        return (
-            <TagInput
-                style={style}
-                value={list}
-                onChange={value => this.handleChange(value)}
-                renderTagItem={(node, index) => this.renderTagItem(node, index)}
-            />
-        );
-    }
+  constructor() {
+    super();
+    this.state = {
+      list: [
+        {
+          name: 'semi',
+          email: '[email protected]',
+          avatar:
+            'https://sf6-cdn-tos.douyinstatic.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/bf8647bffab13c38772c9ff94bf91a9d.jpg',
+        },
+      ],
+    };
+  }
+
+  renderTagItem(node, index) {
+    return (
+      <div
+        key={index}
+        style={{
+          display: 'flex',
+          alignItems: 'center',
+          fontSize: 14,
+          marginRight: 10,
+        }}
+      >
+        <Avatar src={node.avatar} size="extra-small">
+          {node.abbr}
+        </Avatar>
+        <span
+          style={{
+            marginLeft: 8,
+          }}
+        >
+          {node.email}
+        </span>
+      </div>
+    );
+  }
+
+  handleChange(value) {
+    const list = value.map(v => {
+      const item = {};
+      item.name = v.name || v;
+      item.email = `${item.name}@byte.com`;
+      item.avatar = `https://sf6-cdn-tos.douyinstatic.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/bf8647bffab13c38772c9ff94bf91a9d.jpg`;
+      return item;
+    });
+    this.setState({
+      list,
+    });
+  }
+
+  render() {
+    const { list } = this.state;
+    return (
+      <TagInput
+        style={style}
+        value={list}
+        onChange={value => this.handleChange(value)}
+        renderTagItem={(node, index) => this.renderTagItem(node, index)}
+      />
+    );
+  }
 }
 
-stories.add('renderTagItem', () => <CustomRender />);
-stories.add('prefix / suffix', () => (
-    <>
-        <TagInput style={style} prefix={<IconVigoLogo />} showClear />
-        <br />
-        <br />
-        <TagInput style={style} prefix="Prefix" showClear />
-        <br />
-        <br />
-        <TagInput style={style} suffix={<IconGift />} />
-        <br />
-        <br />
-        <TagInput style={style} suffix="Suffix" showClear />
-    </>
-));
+export const RenderTagItem = () => <CustomRender />;
+
+RenderTagItem.story = {
+  name: 'renderTagItem',
+};
+
+export const PrefixSuffix = () => (
+  <>
+    <TagInput style={style} prefix={<IconVigoLogo />} showClear />
+    <br />
+    <br />
+    <TagInput style={style} prefix="Prefix" showClear />
+    <br />
+    <br />
+    <TagInput style={style} suffix={<IconGift />} />
+    <br />
+    <br />
+    <TagInput style={style} suffix="Suffix" showClear />
+  </>
+);
+
+PrefixSuffix.story = {
+  name: 'prefix / suffix',
+};

+ 226 - 165
packages/semi-ui/timePicker/_story/timepicker.stories.js

@@ -1,5 +1,4 @@
 import React, { Component, useState } from 'react';
-import { storiesOf } from '@storybook/react';
 import TimePickerPanel from '../index';
 import { TimePicker as BasicTimePicker, Button } from '../../index';
 import { strings } from '@douyinfe/semi-foundation/timePicker/constants';
@@ -11,193 +10,255 @@ import DisabledTime from './DisabledTime';
 
 let TimePicker;
 
-const stories = storiesOf('timePicker', module);
+export default {
+  title: 'TimePicker',
+  parameters: {
+    chromatic: { disableSnapshot: true },
+  },
+}
+
+export {
+  Callbacks,
+  CustomTrigger,
+  DisabledTime
+}
 
 // auto add scrollItemProps.cycled = false, prevent waiting indefinitely in snapshot testing
 const TimePickerForTest = props => {
-    let scrollItemProps = {};
-    if (!props.scrollItemProps) {
-        scrollItemProps = { cycled: false };
-    } else {
-        scrollItemProps = { ...props.scrollItemProps, cycled: false };
-    }
-    return <BasicTimePicker {...props} scrollItemProps={scrollItemProps} />;
+  let scrollItemProps = {};
+  if (!props.scrollItemProps) {
+    scrollItemProps = { cycled: false };
+  } else {
+    scrollItemProps = { ...props.scrollItemProps, cycled: false };
+  }
+  return <BasicTimePicker {...props} scrollItemProps={scrollItemProps} />;
 };
 
 const init = () => {
-    if (process.env.NODE_ENV === 'development') {
-        TimePicker = BasicTimePicker;
-    } else {
-        TimePicker = TimePickerForTest;
-    }
+  if (process.env.NODE_ENV === 'development') {
+    TimePicker = BasicTimePicker;
+  } else {
+    TimePicker = TimePickerForTest;
+  }
 };
 init();
 
-stories.add('TimePickerPanel default', () => {
+export const TimePickerPanelDefault = () => {
+  return (
+    <div>
+      <TimePicker panelHeader={'Time Select'} onChange={val => console.log(val)} />
+      <TimePicker
+        format={'HH:mm:ss'}
+        defaultValue={'10:24:18'}
+        defaultOpen={true}
+        scrollItemProps={{ cycled: false }}
+      />
+    </div>
+  );
+};
+
+TimePickerPanelDefault.story = {
+  name: 'TimePickerPanel default',
+};
+
+export const BasicUsage = () => <TimePicker />;
+
+BasicUsage.story = {
+  name: 'basic usage',
+};
+
+class Demo extends React.Component {
+  constructor() {
+    super();
+    this.state = {
+      value: null,
+    };
+    this.onChange = this.onChange.bind(this);
+  }
+
+  onChange(time) {
+    //   console.log(time);
+    this.setState({ value: time });
+  }
+
+  render() {
+    return <TimePicker value={this.state.value} onChange={this.onChange} />;
+  }
+}
+
+export const PanelHeader = () => {
+  const Demo = () => {
+    const [value, setValue] = useState(new Date());
+
+    const onChange = (date, str) => setValue(date);
+
     return (
-        <div>
-            <TimePicker panelHeader={'Time Select'} onChange={val => console.log(val)} />
-            <TimePicker format={'HH:mm:ss'} defaultValue={'10:24:18'} defaultOpen={true} scrollItemProps={{ cycled: false }} />
-        </div>
+      <div>
+        <TimePicker panelHeader={'Time Select'} value={new Date()} />
+        <TimePicker panelHeader={'Time Select'} value={value} onChange={onChange} />
+        <TimePicker open />
+      </div>
     );
-});
+  };
 
-stories.add('基础使用', () => <TimePicker />);
+  return <Demo />;
+};
 
-class Demo extends React.Component {
-    constructor() {
-        super();
-        this.state = {
-            value: null,
-        };
-        this.onChange = this.onChange.bind(this);
-    }
-
-    onChange(time) {
-        //   console.log(time);
-        this.setState({ value: time });
-    }
-
-    render() {
-        return <TimePicker value={this.state.value} onChange={this.onChange} />;
-    }
+PanelHeader.story = {
+  name: 'panelHeader',
+};
+
+function CustomDemo() {
+  const [open, setOpen] = useState(false);
+  const closePanel = () => setOpen(false);
+  const onOpenChange = open => {
+    setOpen(open);
+    console.log(open);
+  };
+
+  return (
+    <TimePicker
+      open={open}
+      onOpenChange={onOpenChange}
+      panelHeader={'Time Select'}
+      panelFooter={<Button onClick={closePanel}>close</Button>}
+    />
+  );
 }
 
-stories.add('TimePickerPanel 受控组件', () => {
-    const Demo = () => {
-        const [value, setValue] = useState(new Date());
+export const HeaderAndFooter = () => <CustomDemo />;
+
+HeaderAndFooter.story = {
+  name: 'header and footer',
+};
+
+export const Format = () => <TimePicker format={'HH:mm'} defaultValue={'10:24'} />;
+
+Format.story = {
+  name: 'format',
+};
+
+export const Disabled = () => {
+  return <TimePicker defaultValue={'12:08:23'} disabled />;
+};
+
+Disabled.story = {
+  name: 'disabled',
+};
+
+export const MinuteStepAndSecondStep = () => {
+  return <TimePicker minuteStep={15} secondStep={10} />;
+};
 
-        const onChange = (date, str) => setValue(date);
+MinuteStepAndSecondStep.story = {
+  name: 'minuteStep and secondStep',
+};
 
-        return (
-            <div>
-                <TimePicker panelHeader={'Time Select'} value={new Date()} />
-                <TimePicker panelHeader={'Time Select'} value={value} onChange={onChange} />
-                <TimePicker open />
-            </div>
-        );
+export const InputReadOnly = () => {
+  return <TimePicker inputReadOnly />;
+};
+
+InputReadOnly.story = {
+  name: 'inputReadOnly',
+};
+
+export const RangePicker = () => {
+  const RangePickerDemo = () => {
+    const log = (...args) => {
+      console.log(...args);
     };
 
-    return <Demo />;
-});
+    const disabledHM = { 3: [3, 6, 12, 24, 48], 9: [9, 18, 36] };
+    const disabledHMS = { 6: { 6: [6, 12, 24, 48] }, 18: { 18: [18, 36] } };
 
-function CustomDemo() {
-    const [open, setOpen] = useState(false);
-    const closePanel = () => setOpen(false);
-    const onOpenChange = open => {
-        setOpen(open);
-        console.log(open);
+    const defaultValue = ['10:11:12', '12:11:23'];
+    const [value, setValue] = useState(['10:11:12', '12:11:23']);
+    const disabledHours = () => [1, 2, 4, 8, 16];
+    const disabledMinutes = hours => get(disabledHM, [hours], []);
+    const disabledSeconds = (hours, seconds) => get(disabledHMS, [hours, seconds], []);
+
+    const onChange = (dates, str) => {
+      log(dates, str);
+      setValue(dates);
     };
 
     return (
-        <TimePicker
-            open={open}
-            onOpenChange={onOpenChange}
-            panelHeader={'Time Select'}
-            panelFooter={<Button onClick={closePanel}>close</Button>}
-        />
+      <div style={{ margin: 200 }}>
+        <div>
+          <p>基本</p>
+          <TimePicker type={strings.TYPE_TIME_RANGE_PICKER} onChange={log} />
+        </div>
+        <br />
+        <div>
+          <p>默认值</p>
+          <TimePicker
+            defaultValue={defaultValue}
+            type={strings.TYPE_TIME_RANGE_PICKER}
+            onChange={log}
+          />
+        </div>
+        <div>
+          <p>受控</p>
+          <TimePicker value={value} type={strings.TYPE_TIME_RANGE_PICKER} onChange={onChange} />
+        </div>
+        <div>
+          <p>默认值+format</p>
+          <TimePicker
+            format="HH:mm"
+            disabledHours={disabledHours}
+            disabledMinutes={disabledMinutes}
+            disabledSeconds={disabledSeconds}
+            defaultValue={['10:12', '18:08']}
+            type={strings.TYPE_TIME_RANGE_PICKER}
+            onChange={log}
+          />
+          <br />
+        </div>
+        <div>
+          <p>默认值+use12Hours+format</p>
+          <TimePicker
+            use12Hours
+            format="a hh:mm"
+            disabledHours={disabledHours}
+            disabledMinutes={disabledMinutes}
+            disabledSeconds={disabledSeconds}
+            defaultValue={['上午 10:12', '上午 11:08']}
+            type={strings.TYPE_TIME_RANGE_PICKER}
+            onChange={log}
+            scrollItemProps={{ mode: 'normal' }}
+          />
+          <br />
+        </div>
+      </div>
     );
-}
+  };
 
-stories.add('设置面板头部,底部', () => <CustomDemo />);
-
-stories.add('不同format格式', () => <TimePicker format={'HH:mm'} defaultValue={'10:24'} />);
-
-stories.add('禁用时间选择', () => {
-    return <TimePicker defaultValue={'12:08:23'} disabled />;
-});
-
-stories.add('设置步长', () => {
-    return <TimePicker minuteStep={15} secondStep={10} />;
-});
-
-stories.add('inputReadOnly', () => {
-    return <TimePicker inputReadOnly />;
-});
-
-stories.add('range picker', () => {
-    const RangePickerDemo = () => {
-        const log = (...args) => {
-            console.log(...args);
-        };
-
-        const disabledHM = { 3: [3, 6, 12, 24, 48], 9: [9, 18, 36] };
-        const disabledHMS = { 6: { 6: [6, 12, 24, 48] }, 18: { 18: [18, 36] } };
-
-        const defaultValue = ['10:11:12', '12:11:23'];
-        const [value, setValue] = useState(['10:11:12', '12:11:23']);
-        const disabledHours = () => [1, 2, 4, 8, 16];
-        const disabledMinutes = hours => get(disabledHM, [hours], []);
-        const disabledSeconds = (hours, seconds) => get(disabledHMS, [hours, seconds], []);
-
-        const onChange = (dates, str) => {
-            log(dates, str);
-            setValue(dates);
-        };
-
-        return (
-            <div style={{ margin: 200 }}>
-                <div>
-                    <p>基本</p>
-                    <TimePicker type={strings.TYPE_TIME_RANGE_PICKER} onChange={log} />
-                </div>
-                <br />
-                <div>
-                    <p>默认值</p>
-                    <TimePicker defaultValue={defaultValue} type={strings.TYPE_TIME_RANGE_PICKER} onChange={log} />
-                </div>
-                <div>
-                    <p>受控</p>
-                    <TimePicker value={value} type={strings.TYPE_TIME_RANGE_PICKER} onChange={onChange} />
-                </div>
-                <div>
-                    <p>默认值+format</p>
-                    <TimePicker
-                        format="HH:mm"
-                        disabledHours={disabledHours}
-                        disabledMinutes={disabledMinutes}
-                        disabledSeconds={disabledSeconds}
-                        defaultValue={['10:12', '18:08']}
-                        type={strings.TYPE_TIME_RANGE_PICKER}
-                        onChange={log}
-                    />
-                    <br />
-                </div>
-                <div>
-                    <p>默认值+use12Hours+format</p>
-                    <TimePicker
-                        use12Hours
-                        format="a hh:mm"
-                        disabledHours={disabledHours}
-                        disabledMinutes={disabledMinutes}
-                        disabledSeconds={disabledSeconds}
-                        defaultValue={['上午 10:12', '上午 11:08']}
-                        type={strings.TYPE_TIME_RANGE_PICKER}
-                        onChange={log}
-                        scrollItemProps={{ mode: 'normal' }}
-                    />
-                    <br />
-                </div>
-            </div>
-        );
-    };
+  return <RangePickerDemo />;
+};
+
+RangePicker.story = {
+  name: 'range picker',
+};
+RangePicker.parameters = {
+  chromatic: { disableSnapshot: false },
+}
 
-    return <RangePickerDemo />;
-});
-
-stories.add(`callbacks`, () => <Callbacks />);
-stories.add(`custom trigger`, () => <CustomTrigger />);
-
-stories.add(`disabled time demos`, () => <DisabledTime />);
-
-stories.add(`showClear`, () => {
-    function Demo() {
-        return (
-            <>  
-                <TimePicker defaultValue={new Date()} showClear onChange={(...args) => { console.log('clear', ...args); }} />
-                <TimePicker type="timeRange" defaultValue={new Date(), new Date()} showClear onChange={(...args) => { console.log('clear', ...args); }} />
-            </>
-        );
-    }
-    return <Demo />; 
-});
+export const ShowClear = () => (
+  <>
+    <TimePicker
+      defaultValue={new Date()}
+      showClear
+      onChange={(...args) => {
+        console.log('clear', ...args);
+      }}
+    />
+    <TimePicker
+      type="timeRange"
+      defaultValue={(new Date(), new Date())}
+      showClear
+      onChange={(...args) => {
+        console.log('clear', ...args);
+      }}
+    />
+  </>
+);

+ 159 - 132
packages/semi-ui/timeline/_story/timeline.stories.js

@@ -1,144 +1,171 @@
 import React, { useState } from 'react';
-import { storiesOf } from '@storybook/react'; // import { withKnobs, text, boolean } from '@storybook/addon-knobs';
 
 import Timeline from '../index';
 import { Icon } from '../../index';
 import { IconAlertTriangle } from '@douyinfe/semi-icons';
-const stories = storiesOf('Timeline', module); // stories.addDecorator(withKnobs);;
 
-stories.add('default Timeline', () => (
-    <div>
-        <Timeline>
-            <Timeline.Item time="2015-09-01">创建服务现场</Timeline.Item>
-            <Timeline.Item time="2015-09-01">初步排除网络异常</Timeline.Item>
-            <Timeline.Item time="2015-09-01">技术测试异常</Timeline.Item>
-            <Timeline.Item time="2015-09-01">网络异常正在修复</Timeline.Item>
-        </Timeline>
-    </div>
-));
-stories.add('color', () => (
-    <div>
-        <Timeline>
-            <Timeline.Item time="2015-09-01" type="success">
-                创建服务现场
-            </Timeline.Item>
-            <Timeline.Item time="2015-09-01">初步排除网络异常</Timeline.Item>
-            <Timeline.Item time="2015-09-01" type="warning">
-                技术测试异常
-            </Timeline.Item>
-            <Timeline.Item time="2015-09-01" type="error">
-                网络异常正在修复
-            </Timeline.Item>
-        </Timeline>
+export default {
+  title: 'Timeline'
+}
+
+export const DefaultTimeline = () => (
+  <div>
+    <Timeline>
+      <Timeline.Item time="2015-09-01">创建服务现场</Timeline.Item>
+      <Timeline.Item time="2015-09-01">初步排除网络异常</Timeline.Item>
+      <Timeline.Item time="2015-09-01">技术测试异常</Timeline.Item>
+      <Timeline.Item time="2015-09-01">网络异常正在修复</Timeline.Item>
+    </Timeline>
+  </div>
+);
+
+DefaultTimeline.story = {
+  name: 'default Timeline',
+};
+
+export const Color = () => (
+  <div>
+    <Timeline>
+      <Timeline.Item time="2015-09-01" type="success">
+        创建服务现场
+      </Timeline.Item>
+      <Timeline.Item time="2015-09-01">初步排除网络异常</Timeline.Item>
+      <Timeline.Item time="2015-09-01" type="warning">
+        技术测试异常
+      </Timeline.Item>
+      <Timeline.Item time="2015-09-01" type="error">
+        网络异常正在修复
+      </Timeline.Item>
+    </Timeline>
+  </div>
+);
+
+Color.story = {
+  name: 'color',
+};
+
+export const Custom = () => (
+  <div>
+    <Timeline>
+      <Timeline.Item time="2015-09-01" color="pink">
+        创建服务现场
+      </Timeline.Item>
+      <Timeline.Item time="2015-09-01" color="pink">
+        <span
+          style={{
+            fontSize: '18px',
+          }}
+        >
+          初步排除网络异常
+        </span>
+      </Timeline.Item>
+      <Timeline.Item time="2015-09-01" dot={<IconAlertTriangle />} type="warning">
+        技术测试异常
+      </Timeline.Item>
+      <Timeline.Item time="2015-09-01" extra="节点辅助说明信息">
+        初步排除网络异常
+      </Timeline.Item>
+    </Timeline>
+  </div>
+);
+
+Custom.story = {
+  name: 'custom',
+};
+
+export const Mode = () => (
+  <div>
+    <div
+      style={{
+        width: '300px',
+      }}
+    >
+      <Timeline mode="alternate">
+        <Timeline.Item time="2015-09-01">创建服务现场</Timeline.Item>
+        <Timeline.Item time="2015-09-01">初步排除网络异常</Timeline.Item>
+        <Timeline.Item time="2015-09-01">技术测试异常</Timeline.Item>
+        <Timeline.Item time="2015-09-01">网络异常正在修复</Timeline.Item>
+      </Timeline>
     </div>
-));
-stories.add('custom', () => (
-    <div>
-        <Timeline>
-            <Timeline.Item time="2015-09-01" color="pink">
-                创建服务现场
-            </Timeline.Item>
-            <Timeline.Item time="2015-09-01" color="pink">
-                <span
-                    style={{
-                        fontSize: '18px',
-                    }}
-                >
-                    初步排除网络异常
-                </span>
-            </Timeline.Item>
-            <Timeline.Item time="2015-09-01" dot={<IconAlertTriangle />} type="warning">
-                技术测试异常
-            </Timeline.Item>
-            <Timeline.Item time="2015-09-01" extra="节点辅助说明信息">
-                初步排除网络异常
-            </Timeline.Item>
-        </Timeline>
+    <br />
+    <div
+      style={{
+        width: '300px',
+      }}
+    >
+      <Timeline mode="right">
+        <Timeline.Item time="2015-09-01">创建服务现场</Timeline.Item>
+        <Timeline.Item time="2015-09-01">初步排除网络异常</Timeline.Item>
+        <Timeline.Item time="2015-09-01">技术测试异常</Timeline.Item>
+        <Timeline.Item time="2015-09-01">网络异常正在修复</Timeline.Item>
+      </Timeline>
     </div>
-));
-stories.add('mode', () => (
-    <div>
-        <div
-            style={{
-                width: '300px',
-            }}
-        >
-            <Timeline mode="alternate">
-                <Timeline.Item time="2015-09-01">创建服务现场</Timeline.Item>
-                <Timeline.Item time="2015-09-01">初步排除网络异常</Timeline.Item>
-                <Timeline.Item time="2015-09-01">技术测试异常</Timeline.Item>
-                <Timeline.Item time="2015-09-01">网络异常正在修复</Timeline.Item>
-            </Timeline>
-        </div>
-        <br />
-        <div
-            style={{
-                width: '300px',
-            }}
-        >
-            <Timeline mode="right">
-                <Timeline.Item time="2015-09-01">创建服务现场</Timeline.Item>
-                <Timeline.Item time="2015-09-01">初步排除网络异常</Timeline.Item>
-                <Timeline.Item time="2015-09-01">技术测试异常</Timeline.Item>
-                <Timeline.Item time="2015-09-01">网络异常正在修复</Timeline.Item>
-            </Timeline>
-        </div>
-        <br />
-        <div
-            style={{
-                width: '300px',
-            }}
-        >
-            <Timeline mode="center">
-                <Timeline.Item time="2015-09-01">创建服务现场</Timeline.Item>
-                <Timeline.Item time="2015-09-01">初步排除网络异常</Timeline.Item>
-                <Timeline.Item time="2015-09-01">技术测试异常</Timeline.Item>
-                <Timeline.Item time="2015-09-01">网络异常正在修复</Timeline.Item>
-            </Timeline>
-        </div>
+    <br />
+    <div
+      style={{
+        width: '300px',
+      }}
+    >
+      <Timeline mode="center">
+        <Timeline.Item time="2015-09-01">创建服务现场</Timeline.Item>
+        <Timeline.Item time="2015-09-01">初步排除网络异常</Timeline.Item>
+        <Timeline.Item time="2015-09-01">技术测试异常</Timeline.Item>
+        <Timeline.Item time="2015-09-01">网络异常正在修复</Timeline.Item>
+      </Timeline>
     </div>
-));
+  </div>
+);
+
+Mode.story = {
+  name: 'mode',
+};
+
 const data = [
-    {
-        time: '2019-07-14 10:35',
-        extra: '节点辅助说明信息',
-        content: '创建服务现场',
-        type: 'ongoing',
-    },
-    {
-        time: '2019-06-13 16:17',
-        extra: '节点辅助说明信息',
-        content: (
-            <span
-                style={{
-                    fontSize: '18px',
-                }}
-            >
-                初步排除网络异常
-            </span>
-        ),
-        color: 'pink',
-    },
-    {
-        time: '2019-05-14 18:34',
-        extra: '节点辅助说明信息',
-        dot: <IconAlertTriangle />,
-        content: '技术测试异常',
-        type: 'warning',
-    },
-    {
-        time: '2019-05-09 09:12',
-        extra: '节点辅助说明信息',
-        content: '网络异常正在修复',
-        type: 'success',
-    },
-];
-stories.add('dataSource', () => (
-    <div
+  {
+    time: '2019-07-14 10:35',
+    extra: '节点辅助说明信息',
+    content: '创建服务现场',
+    type: 'ongoing',
+  },
+  {
+    time: '2019-06-13 16:17',
+    extra: '节点辅助说明信息',
+    content: (
+      <span
         style={{
-            width: '400px',
+          fontSize: '18px',
         }}
-    >
-        <Timeline mode="alternate" dataSource={data} />
-    </div>
-));
+      >
+        初步排除网络异常
+      </span>
+    ),
+    color: 'pink',
+  },
+  {
+    time: '2019-05-14 18:34',
+    extra: '节点辅助说明信息',
+    dot: <IconAlertTriangle />,
+    content: '技术测试异常',
+    type: 'warning',
+  },
+  {
+    time: '2019-05-09 09:12',
+    extra: '节点辅助说明信息',
+    content: '网络异常正在修复',
+    type: 'success',
+  },
+];
+
+export const DataSource = () => (
+  <div
+    style={{
+      width: '400px',
+    }}
+  >
+    <Timeline mode="alternate" dataSource={data} />
+  </div>
+);
+
+DataSource.story = {
+  name: 'dataSource',
+};

+ 81 - 70
packages/semi-ui/toast/_story/toast.stories.js

@@ -1,87 +1,98 @@
 import React from 'react';
-import { storiesOf } from '@storybook/react';
-// import { withKnobs, text, boolean } from '@storybook/addon-knobs';
-import withPropsCombinations from 'react-storybook-addon-props-combinations';
-
 import { Toast, ToastFactory } from '../../index';
 
 import Button from '@douyinfe/semi-ui/button/index';
 
-const ToastInContainer = ToastFactory.create({ getPopupContainer: () => document.getElementById('popup-container') })
+export default {
+  title: 'Toast',
+  parameters: {
+    chromatic: { disableSnapshot: true },
+  },
+}
 
-const stories = storiesOf('Toast', module);
+const ToastInContainer = ToastFactory.create({
+  getPopupContainer: () => document.getElementById('popup-container'),
+});
 
-// stories.addDecorator(withKnobs);;
 
 function getContent() {
-    let n = Math.random() * 10;
-    return Array.from({ length: n }, (v, i) => 'dance').join(' ');
+  let n = Math.random() * 10;
+  return Array.from({ length: n }, (v, i) => 'dance').join(' ');
 }
 
 let opts = {
-    title: 'Title ies',
-    content: 'Hi,Bytedance dance dance',
-    duration: 3000,
+  title: 'Title ies',
+  content: 'Hi,Bytedance dance dance',
+  duration: 3000,
 };
 
 let multiOpts = Object.assign({}, opts, {
-    content: 'Hi,Bytedance dance dance, dance dance,dance dance,dance dance',
+  content: 'Hi,Bytedance dance dance, dance dance,dance dance,dance dance',
 });
 
-stories.add('toast', () => (
-    <>
-        <div style={{ margin: '10px' }}>
-            <Button type="primary" onClick={() => Toast.create({ ...opts })}>
-                default
-            </Button>
-        </div>
-        <div style={{ margin: '10px' }}>
-            <Button type="warning" onClick={() => Toast.warning({ ...opts })}>
-                warning
-            </Button>
-        </div>
-        <div style={{ margin: '10px' }}>
-            <Button type="warning" onClick={() => Toast.success('here')}>
-                success
-            </Button>
-        </div>
-        <div style={{ margin: '10px' }}>
-            <Button type="warning" onClick={() => Toast.error({ ...opts })}>
-                error
-            </Button>
-        </div>
-        <div style={{ margin: '10px' }}>
-            <Button type="default" onClick={() => Toast.info({ ...opts, duration: 0 })}>
-                not auto close
-            </Button>
-        </div>
-        <div style={{ margin: '10px' }}>
-            <Button type="default" onClick={() => Toast.destroyAll()}>
-                destroyAll
-            </Button>
-        </div>
-        <div style={{ margin: '10px' }}>
-            <Button type="default" onClick={() => Toast.info({ ...multiOpts, duration: 0 })}>
-                not auto close with muti-line content
-            </Button>
-        </div>
-        <div style={{ margin: '10px' }}>
-            <Button type="danger" onClick={() => {
-                Toast.error({ ...opts, content: 'i am content' })
-            }}>
-                After 3s
-            </Button>
-        </div>
-        <div style={{ width: '300px', height: '300px', background: '#cccccc' }} id="popup-container">
-            popup-container
-        </div>
-        <div>
-            <Button type="primary" onClick={() => {
-                ToastInContainer.info({ content: 'Toast in popup-container' })
-            }}>
-                Toast in popup-container
-            </Button>
-        </div>
-        
-    </>
-));
+export const _Toast = () => (
+  <>
+    <div style={{ margin: '10px' }}>
+      <Button type="primary" onClick={() => Toast.create({ ...opts })}>
+        default
+      </Button>
+    </div>
+    <div style={{ margin: '10px' }}>
+      <Button type="warning" onClick={() => Toast.warning({ ...opts })}>
+        warning
+      </Button>
+    </div>
+    <div style={{ margin: '10px' }}>
+      <Button type="warning" onClick={() => Toast.success('here')}>
+        success
+      </Button>
+    </div>
+    <div style={{ margin: '10px' }}>
+      <Button type="warning" onClick={() => Toast.error({ ...opts })}>
+        error
+      </Button>
+    </div>
+    <div style={{ margin: '10px' }}>
+      <Button type="default" onClick={() => Toast.info({ ...opts, duration: 0 })}>
+        not auto close
+      </Button>
+    </div>
+    <div style={{ margin: '10px' }}>
+      <Button type="default" onClick={() => Toast.destroyAll()}>
+        destroyAll
+      </Button>
+    </div>
+    <div style={{ margin: '10px' }}>
+      <Button type="default" onClick={() => Toast.info({ ...multiOpts, duration: 0 })}>
+        not auto close with muti-line content
+      </Button>
+    </div>
+    <div style={{ margin: '10px' }}>
+      <Button
+        type="danger"
+        onClick={() => {
+          Toast.error({ ...opts, content: 'i am content' });
+        }}
+      >
+        After 3s
+      </Button>
+    </div>
+    <div style={{ width: '300px', height: '300px', background: '#cccccc' }} id="popup-container">
+      popup-container
+    </div>
+    <div>
+      <Button
+        type="primary"
+        onClick={() => {
+          ToastInContainer.info({ content: 'Toast in popup-container' });
+        }}
+      >
+        Toast in popup-container
+      </Button>
+    </div>
+  </>
+);
+
+_Toast.story = {
+  name: 'toast',
+};

+ 579 - 481
packages/semi-ui/tooltip/_story/tooltip.stories.js

@@ -1,5 +1,4 @@
 import React, { useState, useMemo } from 'react';
-import { storiesOf } from '@storybook/react';
 import Tooltip from '../index';
 import './story.scss';
 import { Tag, Icon, IconButton, Switch, Checkbox, Radio, Button, Select } from '@douyinfe/semi-ui';
@@ -11,180 +10,184 @@ import DangerousHtml from './DangerousHtml';
 import ArrowPointAtCenter from './ArrowPointAtCenter';
 import CustomContainer from './CustomContainer';
 import ContainerPosition from './ContainerPosition';
-// // stories.addDecorator(withKnobs);;
 import { IconList, IconSidebar, IconEdit } from '@douyinfe/semi-icons';
 
-const stories = storiesOf('Tooltip', module); // // stories.addDecorator(withKnobs);;
+export default {
+  title: 'Tooltip',
+  parameters: {
+    chromatic: { disableSnapshot: true },
+  },
+}
 
 function test(visible) {
-    console.log('visible Change:' + visible);
+  console.log('visible Change:' + visible);
 }
 
 const ScrollDemo = function ScrollDemo(props = {}) {
-    const tops = [
-        ['topLeft', 'TL'],
-        ['top', 'Top'],
-        ['topRight', 'TR'],
-    ];
-    const lefts = [
-        ['leftTop', 'LT'],
-        ['left', 'Left'],
-        ['leftBottom', 'LB'],
-    ];
-    const rights = [
-        ['rightTop', 'RT'],
-        ['right', 'Right'],
-        ['rightBottom', 'RB'],
-    ];
-    const bottoms = [
-        ['bottomLeft', 'BL'],
-        ['bottom', 'Bottom'],
-        ['bottomRight', 'BR'],
-    ];
-    const { tagStyle, ...restProps } = props;
-    return (
-        <div
-            style={{
-                paddingLeft: 40,
-            }}
-        >
-            <div
-                style={{
-                    marginLeft: 40,
-                    whiteSpace: 'nowrap',
-                }}
-            >
-                {tops.map((pos, index) => (
-                    <Tooltip
-                        content={
-                            <article>
-                                <p>hi bytedance</p>
-                                <p>hi bytedance</p>
-                            </article>
-                        }
-                        position={Array.isArray(pos) ? pos[0] : pos}
-                        key={index}
-                        trigger={'click'}
-                        {...restProps}
-                    >
-                        <Tag style={tagStyle}>{Array.isArray(pos) ? pos[1] : pos}</Tag>
-                    </Tooltip>
-                ))}
-            </div>
-            <div
-                style={{
-                    width: 40,
-                    float: 'left',
-                }}
-            >
-                {lefts.map((pos, index) => (
-                    <Tooltip
-                        content={
-                            <article>
-                                <p>hi bytedance</p>
-                                <p>hi bytedance</p>
-                            </article>
-                        }
-                        position={Array.isArray(pos) ? pos[0] : pos}
-                        key={index}
-                        trigger={'click'}
-                        {...restProps}
-                    >
-                        <Tag style={tagStyle}>{Array.isArray(pos) ? pos[1] : pos}</Tag>
-                    </Tooltip>
-                ))}
-            </div>
-            <div
-                style={{
-                    width: 40,
-                    marginLeft: 180,
-                }}
-            >
-                {rights.map((pos, index) => (
-                    <Tooltip
-                        content={
-                            <article>
-                                <p>hi bytedance</p>
-                                <p>hi bytedance</p>
-                            </article>
-                        }
-                        position={Array.isArray(pos) ? pos[0] : pos}
-                        key={index}
-                        trigger={'click'}
-                        {...restProps}
-                    >
-                        <Tag style={tagStyle}>{Array.isArray(pos) ? pos[1] : pos}</Tag>
-                    </Tooltip>
-                ))}
-            </div>
-            <div
-                style={{
-                    marginLeft: 40,
-                    clear: 'both',
-                    whiteSpace: 'nowrap',
-                }}
-            >
-                {bottoms.map((pos, index) => (
-                    <Tooltip
-                        content={
-                            <article>
-                                <p>hi bytedance</p>
-                                <p>hi bytedance</p>
-                            </article>
-                        }
-                        position={Array.isArray(pos) ? pos[0] : pos}
-                        key={index}
-                        trigger={'click'}
-                        {...restProps}
-                    >
-                        <Tag style={tagStyle}>{Array.isArray(pos) ? pos[1] : pos}</Tag>
-                    </Tooltip>
-                ))}
-            </div>
-        </div>
-    );
+  const tops = [
+    ['topLeft', 'TL'],
+    ['top', 'Top'],
+    ['topRight', 'TR'],
+  ];
+  const lefts = [
+    ['leftTop', 'LT'],
+    ['left', 'Left'],
+    ['leftBottom', 'LB'],
+  ];
+  const rights = [
+    ['rightTop', 'RT'],
+    ['right', 'Right'],
+    ['rightBottom', 'RB'],
+  ];
+  const bottoms = [
+    ['bottomLeft', 'BL'],
+    ['bottom', 'Bottom'],
+    ['bottomRight', 'BR'],
+  ];
+  const { tagStyle, ...restProps } = props;
+  return (
+    <div
+      style={{
+        paddingLeft: 40,
+      }}
+    >
+      <div
+        style={{
+          marginLeft: 40,
+          whiteSpace: 'nowrap',
+        }}
+      >
+        {tops.map((pos, index) => (
+          <Tooltip
+            content={
+              <article>
+                <p>hi bytedance</p>
+                <p>hi bytedance</p>
+              </article>
+            }
+            position={Array.isArray(pos) ? pos[0] : pos}
+            key={index}
+            trigger={'click'}
+            {...restProps}
+          >
+            <Tag style={tagStyle}>{Array.isArray(pos) ? pos[1] : pos}</Tag>
+          </Tooltip>
+        ))}
+      </div>
+      <div
+        style={{
+          width: 40,
+          float: 'left',
+        }}
+      >
+        {lefts.map((pos, index) => (
+          <Tooltip
+            content={
+              <article>
+                <p>hi bytedance</p>
+                <p>hi bytedance</p>
+              </article>
+            }
+            position={Array.isArray(pos) ? pos[0] : pos}
+            key={index}
+            trigger={'click'}
+            {...restProps}
+          >
+            <Tag style={tagStyle}>{Array.isArray(pos) ? pos[1] : pos}</Tag>
+          </Tooltip>
+        ))}
+      </div>
+      <div
+        style={{
+          width: 40,
+          marginLeft: 180,
+        }}
+      >
+        {rights.map((pos, index) => (
+          <Tooltip
+            content={
+              <article>
+                <p>hi bytedance</p>
+                <p>hi bytedance</p>
+              </article>
+            }
+            position={Array.isArray(pos) ? pos[0] : pos}
+            key={index}
+            trigger={'click'}
+            {...restProps}
+          >
+            <Tag style={tagStyle}>{Array.isArray(pos) ? pos[1] : pos}</Tag>
+          </Tooltip>
+        ))}
+      </div>
+      <div
+        style={{
+          marginLeft: 40,
+          clear: 'both',
+          whiteSpace: 'nowrap',
+        }}
+      >
+        {bottoms.map((pos, index) => (
+          <Tooltip
+            content={
+              <article>
+                <p>hi bytedance</p>
+                <p>hi bytedance</p>
+              </article>
+            }
+            position={Array.isArray(pos) ? pos[0] : pos}
+            key={index}
+            trigger={'click'}
+            {...restProps}
+          >
+            <Tag style={tagStyle}>{Array.isArray(pos) ? pos[1] : pos}</Tag>
+          </Tooltip>
+        ))}
+      </div>
+    </div>
+  );
 };
 
-stories.add('tooltip onVisibleChange', () => {
-    const [visible, setVisible] = useState();
-    return (
+export const TooltipOnVisibleChange = () => {
+  const [visible, setVisible] = useState();
+  return (
     <div className="demo">
-        <div>
-            <label>非受控</label>
-            <Tooltip
-                content={
-                    <article>
-                        <p>hi bytedance</p>
-                        <p>hi bytedance</p>
-                    </article>
-                }
-                position="rightBottom"
-                onVisibleChange={test}
-                trigger="click"
-            >
-                <Tag>demo</Tag>
-            </Tooltip>
-        </div>
-        <div>
-            <label>受控</label>
-            <Tooltip
-                content={
-                    <article>
-                        <p>hi bytedance</p>
-                        <p>hi bytedance</p>
-                    </article>
-                }
-                position="rightBottom"
-                onVisibleChange={setVisible}
-                trigger="click"
-                visible={visible}
-            >
-                <Tag>demo</Tag>
-            </Tooltip>
-        </div>
-        <br />
-        <br />
-        {/* <Tooltip
+      <div>
+        <label>非受控</label>
+        <Tooltip
+          content={
+            <article>
+              <p>hi bytedance</p>
+              <p>hi bytedance</p>
+            </article>
+          }
+          position="rightBottom"
+          onVisibleChange={test}
+          trigger="click"
+        >
+          <Tag>demo</Tag>
+        </Tooltip>
+      </div>
+      <div>
+        <label>受控</label>
+        <Tooltip
+          content={
+            <article>
+              <p>hi bytedance</p>
+              <p>hi bytedance</p>
+            </article>
+          }
+          position="rightBottom"
+          onVisibleChange={setVisible}
+          trigger="click"
+          visible={visible}
+        >
+          <Tag>demo</Tag>
+        </Tooltip>
+      </div>
+      <br />
+      <br />
+      {/* <Tooltip
        content={
            <article>
                <p>hi bytedance</p>
@@ -229,341 +232,436 @@ stories.add('tooltip onVisibleChange', () => {
        <Tag>click</Tag>
     </Tooltip> */}
     </div>
-)});
+  );
+};
 
-stories.add('tooltip指定弹出层的容器', () => (
-    <div className="demo">
-        <div className="content-layer" />
-        <Tooltip
-            content={
-                <article>
-                    <p>hi bytedance</p> <p>hi bytedance</p>
-                </article>
-            }
-            position="bottom"
-            visible
-            trigger="custom"
-            getPopupContainer={() => document.querySelector('.content-layer')}
-        >
-            <Tag>指定弹出层的容器</Tag>
-            {/* <div className='content'></div> */}
-        </Tooltip>
-        <div>
-            <label>给定容器为window,看是否报错</label>
-            <Tooltip content={'单选'} position="top" getPopupContainer={() => window}>
-                <Radio style={{ display: 'inline-flex' }}>单选</Radio>
-            </Tooltip>
-        </div>
+TooltipOnVisibleChange.story = {
+  name: 'tooltip onVisibleChange',
+};
+
+export const GetPopupContainerDemo = () => (
+  <div className="demo">
+    <div className="content-layer" />
+    <Tooltip
+      content={
+        <article>
+          <p>hi bytedance</p> <p>hi bytedance</p>
+        </article>
+      }
+      position="bottom"
+      visible
+      trigger="custom"
+      getPopupContainer={() => document.querySelector('.content-layer')}
+    >
+      <Tag>指定弹出层的容器</Tag>
+      {/* <div className='content'></div> */}
+    </Tooltip>
+    <div>
+      <label>给定容器为window,看是否报错</label>
+      <Tooltip content={'单选'} position="top" getPopupContainer={() => window}>
+        <Radio style={{ display: 'inline-flex' }}>单选</Radio>
+      </Tooltip>
     </div>
-));
-stories.add('tooltip All', () => (
-    <div className="demo">
-        <ScrollDemo />
-        <div
-            style={{
-                padding: 120,
-            }}
-        >
-            <ScrollDemo
-                showArrow
-                tagStyle={{
-                    height: 80,
-                }}
-            />
-        </div>
+  </div>
+);
+
+GetPopupContainerDemo.story = {
+  name: 'tooltip指定弹出层的容器',
+};
+
+export const TooltipAll = () => (
+  <div className="demo">
+    <ScrollDemo />
+    <div
+      style={{
+        padding: 120,
+      }}
+    >
+      <ScrollDemo
+        showArrow
+        tagStyle={{
+          height: 80,
+        }}
+      />
     </div>
-));
-stories.add('no content', () => (
-    <div className="demo">
-        <div
-            style={{
-                padding: 120,
-            }}
-        >
-            <ScrollDemo showArrow content={''} />
-        </div>
-        <div
-            style={{
-                padding: 120,
-            }}
-        >
-            <ScrollDemo
-                showArrow
-                tagStyle={{
-                    minHeight: 80,
-                    minWidth: 120,
-                }}
-                content={''}
-            />
-        </div>
+  </div>
+);
+
+TooltipAll.story = {
+  name: 'tooltip All',
+};
+
+export const NoContent = () => (
+  <div className="demo">
+    <div
+      style={{
+        padding: 120,
+      }}
+    >
+      <ScrollDemo showArrow content={''} />
     </div>
-));
-stories.add('自适应', () => (
-    <>
-        <div className="adjust">
-            <div className="wrapper">
-                第一个滚动区域
-                <Tooltip
-                    content={
-                        <article>
-                            <p>hi bytedance</p>
-                            <p>hi bytedance</p>
-                        </article>
-                    }
-                    position="rightBottom"
-                    trigger="click"
-                >
-                    {/* <Tag className='topLeft'>topleft</Tag> */}
-                    <div>test</div>
-                </Tooltip>
-                <Tooltip
-                    content={
-                        <article>
-                            <p>hi bytedance</p>
-                            <p>hi bytedance</p>
-                        </article>
-                    }
-                    position="topRight"
-                    trigger="click"
-                >
-                    <Tag className="topRight">topRight</Tag>
-                </Tooltip>
-                <Tooltip
-                    content={
-                        <article>
-                            <p>hi bytedance</p>
-                            <p>hi bytedance</p>
-                        </article>
-                    }
-                    position="bottomLeft"
-                    trigger="click"
-                >
-                    <Tag className="bottomLeft">bottomLeft</Tag>
-                </Tooltip>
-                <Tooltip
-                    content={
-                        <article>
-                            <p>hi bytedance</p>
-                            <p>hi bytedance</p>
-                        </article>
-                    }
-                    position="bottomRight"
-                    trigger="click"
-                >
-                    <Tag className="bottomRight">bottomRight</Tag>
-                </Tooltip>
-            </div>
-        </div>
-        <div className="adjust2">
-            <div className="wrapper2">第二个滚动区域</div>
-        </div>
-    </>
-));
-stories.add('复合组件', () => (
     <div
-        style={{
-            padding: 50,
-        }}
+      style={{
+        padding: 120,
+      }}
     >
+      <ScrollDemo
+        showArrow
+        tagStyle={{
+          minHeight: 80,
+          minWidth: 120,
+        }}
+        content={''}
+      />
+    </div>
+  </div>
+);
+
+NoContent.story = {
+  name: 'no content',
+};
+
+export const AdjustPosition = () => (
+  <>
+    <div className="adjust">
+      <div className="wrapper">
+        第一个滚动区域
         <Tooltip
-            content={
-                <article>
-                    <p>hi bytedance</p> <p>hi bytedance</p>
-                </article>
-            }
-            position="top"
+          content={
+            <article>
+              <p>hi bytedance</p>
+              <p>hi bytedance</p>
+            </article>
+          }
+          position="rightBottom"
+          trigger="click"
         >
-            <IconList />
-        </Tooltip>
-        <Tooltip content={'收起'} position="top">
-            <IconButton icon={<IconSidebar />} />
+          {/* <Tag className='topLeft'>topleft</Tag> */}
+          <div>test</div>
         </Tooltip>
-        <Tooltip content={'开关'} position="top">
-            <Switch />
+        <Tooltip
+          content={
+            <article>
+              <p>hi bytedance</p>
+              <p>hi bytedance</p>
+            </article>
+          }
+          position="topRight"
+          trigger="click"
+        >
+          <Tag className="topRight">topRight</Tag>
         </Tooltip>
-        <Tooltip content={'选择框'} position="top">
-            <Checkbox
-                style={{
-                    display: 'inline-flex',
-                }}
-            >
-                选择框
-            </Checkbox>
+        <Tooltip
+          content={
+            <article>
+              <p>hi bytedance</p>
+              <p>hi bytedance</p>
+            </article>
+          }
+          position="bottomLeft"
+          trigger="click"
+        >
+          <Tag className="bottomLeft">bottomLeft</Tag>
         </Tooltip>
-        <Tooltip content={'单选'} position="top">
-            <Radio
-                style={{
-                    display: 'inline-flex',
-                }}
-            >
-                单选
-            </Radio>
+        <Tooltip
+          content={
+            <article>
+              <p>hi bytedance</p>
+              <p>hi bytedance</p>
+            </article>
+          }
+          position="bottomRight"
+          trigger="click"
+        >
+          <Tag className="bottomRight">bottomRight</Tag>
         </Tooltip>
+      </div>
     </div>
-));
-stories.add('wrap disabled elems', () => (
-    <div
+    <div className="adjust2">
+      <div className="wrapper2">第二个滚动区域</div>
+    </div>
+  </>
+);
+
+AdjustPosition.story = {
+  name: '自适应'
+}
+
+export const CompositeComponent = () => (
+  <div
+    style={{
+      padding: 50,
+    }}
+  >
+    <Tooltip
+      content={
+        <article>
+          <p>hi bytedance</p> <p>hi bytedance</p>
+        </article>
+      }
+      position="top"
+    >
+      <IconList />
+    </Tooltip>
+    <Tooltip content={'收起'} position="top">
+      <IconButton icon={<IconSidebar />} />
+    </Tooltip>
+    <Tooltip content={'开关'} position="top">
+      <Switch />
+    </Tooltip>
+    <Tooltip content={'选择框'} position="top">
+      <Checkbox
         style={{
-            padding: 50,
+          display: 'inline-flex',
         }}
-    >
-        <Tooltip content="disabled">
-            <IconButton disabled icon={<IconEdit />} />
-        </Tooltip>
-        <Tooltip content="disabled">
-            <IconButton disabled icon={<IconEdit />} block />
-        </Tooltip>
-        <Tooltip content="disabled">
-            <Button disabled block>
-                编辑
-            </Button>
-        </Tooltip>
-        <Tooltip content="disabled">
-            <Button
-                disabled
-                style={{
-                    display: 'block',
-                }}
-            >
-                编辑
-            </Button>
-        </Tooltip>
-    </div>
-));
-stories.add('in table', () => (
-    <div
+      >
+        选择框
+      </Checkbox>
+    </Tooltip>
+    <Tooltip content={'单选'} position="top">
+      <Radio
         style={{
-            marginTop: 50,
+          display: 'inline-flex',
         }}
-    >
-        <InTableDemo />
-    </div>
-));
-stories.add('edge demo', () => <EdgeDemo />);
-stories.add(`scroll demo and set popup container`, () => <ScrollTooltip />);
-stories.add(`in dangerous html`, () => <DangerousHtml />);
-stories.add(`arrow point at center`, () => <ArrowPointAtCenter />);
-stories.add(`custom container`, () => <CustomContainer />);
-stories.add(`container observer`, () => <ContainerPosition />);
-
-stories.add('快速移动鼠标可见性', () => {
-    /**
-     * mouseEnterDelay, mouseLeaveDelay 默认都为 50
-     * mouseEnterDelay, mouseLeaveDelay 都为 0,快速滑动可能出现两个 tooltip 出现
-     */
-    const Demo = () => {
-        const props = {
-            mouseEnterDelay: 50,
-            mouseLeaveDelay: 0,
-        }
-        return (
-          <div className="demo">
-            <div>
-                <Tooltip content={'1'} {...props}>aaaaaaaaaaa</Tooltip>
-            </div>
-            <div>
-                <Tooltip content={'2'} {...props}>bbbbbbbbbbb</Tooltip>
-            </div>
-            <div>
-                <Tooltip content={'3'} {...props}>ccccccccccc</Tooltip>
-            </div>
-            <div>
-                <Tooltip content={'4'} {...props}>aaaaaaaaaaa</Tooltip>
-            </div>
-            <div>
-                <Tooltip content={'5'} {...props}>bbbbbbbbbbb</Tooltip>
-            </div>
-            <div>
-                <Tooltip content={'6'} {...props}>ccccccccccc</Tooltip>
-            </div>
-            <div>
-                <Tooltip content={'7'} {...props}>aaaaaaaaaaa</Tooltip>
-            </div>
-            <div>
-                <Tooltip content={'8'} {...props}>bbbbbbbbbbb</Tooltip>
-            </div>
-            <div>
-                <Tooltip content={'9'} {...props}>ccccccccccc</Tooltip>
-            </div>
-          </div>
-        )
-      }
-      
-    return <Demo />
-});
-
-stories.add('motion=false fix #1402', () => {
-
-    function Demo() {
-        const Test = React.forwardRef((props, ref) => (
-            <span {...props} ref={ref}>
-                Test
-            </span>
-        ));
-        return (
-            <div>
-                <Tooltip content={'hi bytedance'} motion={false} >
-                    <Test />
-                </Tooltip>
-                <br /><br />
-                <Tooltip content={'hi bytedance'}>
-                    <Test />
-                </Tooltip>
-            </div>
-        );
-    }
-      
-    return <Demo />
-});
-
-stories.add('disabledWrapperCls', () => (
-    <>
-        <Tooltip wrapperClassName='test' content={'hi bytedance'}>
-            <Button>按钮</Button>
-        </Tooltip>
-        <br />
-        <br />
-        <Tooltip wrapperClassName='test' content={'hi bytedance'}>
-            <Button disabled>禁用的单个按钮</Button>
+      >
+        单选
+      </Radio>
+    </Tooltip>
+  </div>
+);
+
+CompositeComponent.story = {
+  name: '复合组件'
+}
+
+export const WrapDisabledElems = () => (
+  <div
+    style={{
+      padding: 50,
+    }}
+  >
+    <Tooltip content="disabled">
+      <IconButton disabled icon={<IconEdit />} />
+    </Tooltip>
+    <Tooltip content="disabled">
+      <IconButton disabled icon={<IconEdit />} block />
+    </Tooltip>
+    <Tooltip content="disabled">
+      <Button disabled block>
+        编辑
+      </Button>
+    </Tooltip>
+    <Tooltip content="disabled">
+      <Button
+        disabled
+        style={{
+          display: 'block',
+        }}
+      >
+        编辑
+      </Button>
+    </Tooltip>
+  </div>
+);
+
+WrapDisabledElems.story = {
+  name: 'wrap disabled elems',
+};
+
+export const InTable = () => (
+  <div
+    style={{
+      marginTop: 50,
+    }}
+  >
+    <InTableDemo />
+  </div>
+);
+
+InTable.story = {
+  name: 'in table',
+};
+
+export const _EdgeDemo = () => <EdgeDemo />;
+
+_EdgeDemo.story = {
+  name: 'edge demo',
+};
+
+export const ScrollTooltipDemo = () => <ScrollTooltip />;
+ScrollTooltipDemo.story = {
+  name: 'scroll demo and set popup container'
+}
+export const DangerousHtmlDemo = () => <DangerousHtml />;
+DangerousHtmlDemo.story = {
+  name: 'in dangerous html'
+}
+export const ArrowPointAtCenterDemo = () => <ArrowPointAtCenter />;
+ArrowPointAtCenterDemo.story = {
+  name: 'arrow point at center'
+}
+export const CustomContainerDemo = () => <CustomContainer />;
+CustomContainerDemo.story = {
+  name: 'custom container'
+}
+export const ContainerPositionDemo = () => <ContainerPosition />;
+ContainerPositionDemo.story = {
+  name: 'container observer'
+}
+
+export const QuickMoveMouse = () => {
+  /**
+   * mouseEnterDelay, mouseLeaveDelay 默认都为 50
+   * mouseEnterDelay, mouseLeaveDelay 都为 0,快速滑动可能出现两个 tooltip 出现
+   */
+  const Demo = () => {
+    const props = {
+      mouseEnterDelay: 50,
+      mouseLeaveDelay: 0,
+    };
+    return (
+      <div className="demo">
+        <div>
+          <Tooltip content={'1'} {...props}>
+            aaaaaaaaaaa
+          </Tooltip>
+        </div>
+        <div>
+          <Tooltip content={'2'} {...props}>
+            bbbbbbbbbbb
+          </Tooltip>
+        </div>
+        <div>
+          <Tooltip content={'3'} {...props}>
+            ccccccccccc
+          </Tooltip>
+        </div>
+        <div>
+          <Tooltip content={'4'} {...props}>
+            aaaaaaaaaaa
+          </Tooltip>
+        </div>
+        <div>
+          <Tooltip content={'5'} {...props}>
+            bbbbbbbbbbb
+          </Tooltip>
+        </div>
+        <div>
+          <Tooltip content={'6'} {...props}>
+            ccccccccccc
+          </Tooltip>
+        </div>
+        <div>
+          <Tooltip content={'7'} {...props}>
+            aaaaaaaaaaa
+          </Tooltip>
+        </div>
+        <div>
+          <Tooltip content={'8'} {...props}>
+            bbbbbbbbbbb
+          </Tooltip>
+        </div>
+        <div>
+          <Tooltip content={'9'} {...props}>
+            ccccccccccc
+          </Tooltip>
+        </div>
+      </div>
+    );
+  };
+
+  return <Demo />;
+};
+
+QuickMoveMouse.story = {
+  name: '快速移动鼠标可见性'
+}
+
+export const MotionFalseFix1402 = () => {
+  function Demo() {
+    const Test = React.forwardRef((props, ref) => (
+      <span {...props} ref={ref}>
+        Test
+      </span>
+    ));
+    return (
+      <div>
+        <Tooltip content={'hi bytedance'} motion={false}>
+          <Test />
         </Tooltip>
         <br />
         <br />
-        <Tooltip wrapperClassName='test' content={'hi bytedance'}>
-            <Button>正常的多个按钮</Button>
-            <Button>正常的多个按钮</Button>
+        <Tooltip content={'hi bytedance'}>
+          <Test />
         </Tooltip>
-        <br />
-        <br />
-        <Tooltip wrapperClassName='test' content={'hi bytedance'}>
-            <Select disabled placeholder='请选择业务线' style={{ width: 120 }}>
-                <Select.Option value='abc'>抖音</Select.Option>
-                <Select.Option value='hotsoon'>火山</Select.Option>
-                <Select.Option value='jianying' disabled>剪映</Select.Option>
-                <Select.Option value='xigua'>西瓜视频</Select.Option>
-            </Select>
+      </div>
+    );
+  }
+
+  return <Demo />;
+};
+
+MotionFalseFix1402.story = {
+  name: 'motion=false fix #1402',
+};
+
+export const DisabledWrapperCls = () => (
+  <>
+    <Tooltip wrapperClassName="test" content={'hi bytedance'}>
+      <Button>按钮</Button>
+    </Tooltip>
+    <br />
+    <br />
+    <Tooltip wrapperClassName="test" content={'hi bytedance'}>
+      <Button disabled>禁用的单个按钮</Button>
+    </Tooltip>
+    <br />
+    <br />
+    <Tooltip wrapperClassName="test" content={'hi bytedance'}>
+      <Button>正常的多个按钮</Button>
+      <Button>正常的多个按钮</Button>
+    </Tooltip>
+    <br />
+    <br />
+    <Tooltip wrapperClassName="test" content={'hi bytedance'}>
+      <Select disabled placeholder="请选择业务线" style={{ width: 120 }}>
+        <Select.Option value="abc">抖音</Select.Option>
+        <Select.Option value="hotsoon">火山</Select.Option>
+        <Select.Option value="jianying" disabled>
+          剪映
+        </Select.Option>
+        <Select.Option value="xigua">西瓜视频</Select.Option>
+      </Select>
+    </Tooltip>
+    <br />
+    <br />
+  </>
+);
+
+DisabledWrapperCls.story = {
+  name: 'disabledWrapperCls',
+};
+
+export const ShowArrow = () => {
+  function Demo() {
+    const Test = React.forwardRef((props, ref) => (
+      <Tag {...props} ref={ref}>
+        Test
+      </Tag>
+    ));
+    return (
+      <div>
+        <h4>should show content and arrow when click</h4>
+        <Tooltip showArrow trigger="click" content={'hi bytedance'}>
+          <Test />
         </Tooltip>
-        <br />
-        <br />
-    </>
-));
-
-stories.add('showArrow', () => {
-
-    function Demo() {
-        const Test = React.forwardRef((props, ref) => (
-            <Tag {...props} ref={ref}>
-                Test
-            </Tag>
-        ));
-        return (
-            <div>
-                <h4>should show content and arrow when click</h4>
-                <Tooltip showArrow trigger="click" content={'hi bytedance'} >
-                    <Test />
-                </Tooltip>
-            </div>
-        );
-    }
-      
-    return <Demo />
-})
+      </div>
+    );
+  }
+
+  return <Demo />;
+};
+
+ShowArrow.story = {
+  name: 'showArrow',
+};

+ 667 - 584
packages/semi-ui/transfer/_story/transfer.stories.js

@@ -1,9 +1,5 @@
 import React, { useState, useRef } from 'react';
-import { storiesOf } from '@storybook/react';
-// import { Input, Transfer, Button, Icon, Avatar, Checkbox } from '../index';
-// import Transfer from '../index';
 import { Transfer, Button } from '../../index';
-// import Input from '../../input';
 import Table from '../../table';
 import Avatar from '../../avatar';
 import Checkbox from '../../checkbox';
@@ -13,663 +9,750 @@ import Input from '../../input';
 import { omit, values } from 'lodash-es';
 import './transfer.scss';
 import { SortableContainer, SortableElement, sortableHandle } from 'react-sortable-hoc';
-import {IconClose, IconSearch, IconHandle} from '@douyinfe/semi-icons';
+import { IconClose, IconSearch, IconHandle } from '@douyinfe/semi-icons';
 
-const stories = storiesOf('Transfer', module);
+export default {
+  title: 'Transfer'
+}
 
 const commonProps = {
-    onSelect: (...args) => {
-        console.log('onSelect');
-        console.log(...args);
-    },
-    onChange: (...args) => {
-        console.log('onChange');
-        console.log(...args);
-    },
-    onDeselect: (...args) => {
-        console.log('onDeselect');
-        console.log(...args);
-    },
-    onSearch: (...args) => {
-        console.log('onSearch');
-        console.log(...args);
-    },
+  onSelect: (...args) => {
+    console.log('onSelect');
+    console.log(...args);
+  },
+  onChange: (...args) => {
+    console.log('onChange');
+    console.log(...args);
+  },
+  onDeselect: (...args) => {
+    console.log('onDeselect');
+    console.log(...args);
+  },
+  onSearch: (...args) => {
+    console.log('onSearch');
+    console.log(...args);
+  },
 };
 
 const data = Array.from({ length: 100 }, (v, i) => {
-    return {
-        label: `选项名称${i}`,
-        value: i,
-        disabled: false,
-        key: i,
-    };
+  return {
+    label: `选项名称${i}`,
+    value: i,
+    disabled: false,
+    key: i,
+  };
 });
 
 const treeData = [
-    {
-        label: 'Asia',
-        value: 'Asia',
-        key: '0',
+  {
+    label: 'Asia',
+    value: 'Asia',
+    key: '0',
+    children: [
+      {
+        label: 'China',
+        value: 'China',
+        key: '0-0',
         children: [
-            {
-                label: 'China',
-                value: 'China',
-                key: '0-0',
-                children: [
-                    {
-                        label: 'Beijing',
-                        value: 'Beijing',
-                        key: '0-0-0',
-                        disabled: true,
-                    },
-                    {
-                        label: 'ShanghaionChangeonChangeonChange',
-                        value: 'Shanghai',
-                        key: '0-0-1',
-                    },
-                    {
-                        label: 'Chengdu',
-                        value: 'Chengdu',
-                        key: '0-0-2',
-                    },
-                    {
-                        label: 'Chongqing',
-                        value: 'Chongqing',
-                        key: '0-0-3',
-                    },
-                ],
-            },
-            {
-                label: 'Japan',
-                value: 'Japan',
-                key: '0-1',
-                children: [
-                    {
-                        label: 'Osaka',
-                        value: 'Osaka',
-                        key: '0-1-0',
-                    },
-                ],
-            },
+          {
+            label: 'Beijing',
+            value: 'Beijing',
+            key: '0-0-0',
+            disabled: true,
+          },
+          {
+            label: 'ShanghaionChangeonChangeonChange',
+            value: 'Shanghai',
+            key: '0-0-1',
+          },
+          {
+            label: 'Chengdu',
+            value: 'Chengdu',
+            key: '0-0-2',
+          },
+          {
+            label: 'Chongqing',
+            value: 'Chongqing',
+            key: '0-0-3',
+          },
         ],
-    },
-    {
-        label: 'North America',
-        value: 'North America',
-        key: '1',
+      },
+      {
+        label: 'Japan',
+        value: 'Japan',
+        key: '0-1',
         children: [
-            {
-                label: 'United States',
-                value: 'United States',
-                key: '1-0',
-            },
-            {
-                label: 'Canada',
-                value: 'Canada',
-                key: '1-1',
-            },
+          {
+            label: 'Osaka',
+            value: 'Osaka',
+            key: '0-1-0',
+          },
         ],
-    },
+      },
+    ],
+  },
+  {
+    label: 'North America',
+    value: 'North America',
+    key: '1',
+    children: [
+      {
+        label: 'United States',
+        value: 'United States',
+        key: '1-0',
+      },
+      {
+        label: 'Canada',
+        value: 'Canada',
+        key: '1-1',
+      },
+    ],
+  },
 ];
 
 const dataWithGroup = [
-    {
-        title: '类别A',
-        children: [
-            { label: '选项名称1', value: 1, disabled: false, key: 1 },
-            { label: '选项名称2', value: 2, disabled: false, key: 2 },
-            { label: '选项名称3', value: 3, disabled: false, key: 3 },
-        ],
-    },
-    {
-        title: '类别B',
-        children: [
-            { label: '选项名称1', value: 4, disabled: true, key: 4 },
-            { label: '选项名称2', value: 5, disabled: false, key: 5 },
-            { label: '选项名称3', value: 6, disabled: false, key: 6 },
-        ],
-    },
-    {
-        title: '类别C',
-        children: [
-            { label: '选项名称1', value: 7, disabled: false, key: 7 },
-            { label: '选项名称2', value: 8, disabled: false, key: 8 },
-            { label: '选项名称3', value: 9, disabled: false, key: 9 },
-            { label: '选项名称3', value: 10, disabled: false, key: 10 },
-            { label: '选项名称3', value: 11, disabled: false, key: 11 },
-            { label: '选项名称3', value: 12, disabled: false, key: 12 },
-            { label: '选项名称3', value: 13, disabled: false, key: 13 },
-        ],
-    },
+  {
+    title: '类别A',
+    children: [
+      { label: '选项名称1', value: 1, disabled: false, key: 1 },
+      { label: '选项名称2', value: 2, disabled: false, key: 2 },
+      { label: '选项名称3', value: 3, disabled: false, key: 3 },
+    ],
+  },
+  {
+    title: '类别B',
+    children: [
+      { label: '选项名称1', value: 4, disabled: true, key: 4 },
+      { label: '选项名称2', value: 5, disabled: false, key: 5 },
+      { label: '选项名称3', value: 6, disabled: false, key: 6 },
+    ],
+  },
+  {
+    title: '类别C',
+    children: [
+      { label: '选项名称1', value: 7, disabled: false, key: 7 },
+      { label: '选项名称2', value: 8, disabled: false, key: 8 },
+      { label: '选项名称3', value: 9, disabled: false, key: 9 },
+      { label: '选项名称3', value: 10, disabled: false, key: 10 },
+      { label: '选项名称3', value: 11, disabled: false, key: 11 },
+      { label: '选项名称3', value: 12, disabled: false, key: 12 },
+      { label: '选项名称3', value: 13, disabled: false, key: 13 },
+    ],
+  },
 ];
 
 const DefaultTransfer = () => {
-    const [dataSource, setDataSource] = useState([]);
-    const [treeDataSource, setTreeDataSource] = useState([]);
-    return (
-        <div style={{ margin: 10, padding: 10, width: 600 }}>
-            <Button onClick={() => setDataSource(data)}>更改列表数据源</Button>
-            <Transfer {...commonProps} dataSource={dataSource} defaultValue={[]} />
-            <Button onClick={() => setTreeDataSource(treeData)}>更改树数据源</Button>
-            <Transfer type="treeList" dataSource={treeDataSource}></Transfer>
-        </div>
-    );
+  const [dataSource, setDataSource] = useState([]);
+  const [treeDataSource, setTreeDataSource] = useState([]);
+  return (
+    <div style={{ margin: 10, padding: 10, width: 600 }}>
+      <Button onClick={() => setDataSource(data)}>更改列表数据源</Button>
+      <Transfer {...commonProps} dataSource={dataSource} defaultValue={[]} />
+      <Button onClick={() => setTreeDataSource(treeData)}>更改树数据源</Button>
+      <Transfer type="treeList" dataSource={treeDataSource}></Transfer>
+    </div>
+  );
 };
 
-stories.add('Transfer', DefaultTransfer);
+export const _Transfer = DefaultTransfer;
 
-stories.add('Transfer draggable', () => (
-    <div style={{ margin: 10, padding: 10, width: 600 }}>
-        <Transfer {...commonProps} dataSource={data} defaultValue={[2, 4]} draggable />
-    </div>
-));
+export const TransferDraggable = () => (
+  <div style={{ margin: 10, padding: 10, width: 600 }}>
+    <Transfer {...commonProps} dataSource={data} defaultValue={[2, 4]} draggable />
+  </div>
+);
+
+TransferDraggable.story = {
+  name: 'Transfer draggable',
+};
 
 const ControledTransfer = () => {
-    const [value, setValue] = useState([2, 3]);
+  const [value, setValue] = useState([2, 3]);
 
-    const handleChange = value => {
-        setValue(value);
-    };
+  const handleChange = value => {
+    setValue(value);
+  };
 
-    return (
-        <div style={{ margin: 10, padding: 10, width: 600 }}>
-            <Transfer {...commonProps} dataSource={data} value={value} onChange={handleChange} />
-        </div>
-    );
+  return (
+    <div style={{ margin: 10, padding: 10, width: 600 }}>
+      <Transfer {...commonProps} dataSource={data} value={value} onChange={handleChange} />
+    </div>
+  );
 };
 
-stories.add('受控Transfer', () => <ControledTransfer />);
+export const ControlledTransfer = () => <ControledTransfer />;
 
-stories.add('loading', () => <Transfer loading />);
+ControlledTransfer.story = {
+  name: '受控Transfer',
+};
 
-stories.add('分组Transfer', () => (
-    <div style={{ margin: 10, padding: 10, width: 600 }}>
-        <Transfer {...commonProps} dataSource={dataWithGroup} type="groupList" />
+export const Loading = () => <Transfer loading />;
 
-        <Transfer {...commonProps} dataSource={dataWithGroup} defaultValue={[2, 4]} type="groupList" />
-    </div>
-));
+Loading.story = {
+  name: 'loading',
+};
+
+export const GroupTransfer = () => (
+  <div style={{ margin: 10, padding: 10, width: 600 }}>
+    <Transfer {...commonProps} dataSource={dataWithGroup} type="groupList" />
+
+    <Transfer {...commonProps} dataSource={dataWithGroup} defaultValue={[2, 4]} type="groupList" />
+  </div>
+);
+
+GroupTransfer.story = {
+  name: '分组Transfer',
+};
 
 const customFilter = (sugInput, item) => {
-    return item.value.includes(sugInput) || item.label.includes(sugInput);
+  return item.value.includes(sugInput) || item.label.includes(sugInput);
 };
 
-stories.add('custom filter, renderSourceItem, renderSelectedItem', () => {
-    const data = [
-        { label: '夏可漫', value: '[email protected]', abbr: '夏', color: 'amber', area: 'US', key: 1 },
-        { label: '申悦', value: '[email protected]', abbr: '申', color: 'indigo', area: 'UK', key: 2 },
-        { label: '文嘉茂', value: '[email protected]', abbr: '文', color: 'cyan', area: 'HK', key: 3 },
-        { label: '曲晨一', value: '[email protected]', abbr: '一', color: 'blue', area: 'India', key: 4 },
-        { label: '曲晨二', value: '[email protected]', abbr: '二', color: 'blue', area: 'India', key: 5 },
-        { label: '曲晨三', value: '[email protected]', abbr: '三', color: 'blue', area: 'India', key: 6 },
-    ];
-
-    const renderSourceItem = item => {
-        return (
-            <div className="components-transfer-demo-source-item">
-                <Checkbox
-                    onChange={() => {
-                        item.onChange();
-                    }}
-                    key={item.label}
-                    checked={item.checked}
-                    style={{ paddingLeft: 12, height: 52 }}
-                >
-                    <Avatar color={item.color} size="small">
-                        {item.abbr}
-                    </Avatar>
-                    <div className="info">
-                        <div className="name">{item.label}</div>
-                        <div className="email">{item.value}</div>
-                    </div>
-                </Checkbox>
-            </div>
-        );
-    };
-    const renderSelectedItem = item => {
-        return (
-            <div className="components-transfer-demo-selected-item" key={item.label}>
-                <Avatar color={item.color} size="small">
-                    {item.abbr}
-                </Avatar>
-                <div className="info">
-                    <div className="name">{item.label}</div>
-                    <div className="email">{item.value}</div>
-                </div>
-                <IconClose onClick={item.onRemove} />
-            </div>
-        );
-    };
+export const CustomFilterRenderSourceItemRenderSelectedItem = () => {
+  const data = [
+    {
+      label: '夏可漫',
+      value: '[email protected]',
+      abbr: '夏',
+      color: 'amber',
+      area: 'US',
+      key: 1,
+    },
+    {
+      label: '申悦',
+      value: '[email protected]',
+      abbr: '申',
+      color: 'indigo',
+      area: 'UK',
+      key: 2,
+    },
+    {
+      label: '文嘉茂',
+      value: '[email protected]',
+      abbr: '文',
+      color: 'cyan',
+      area: 'HK',
+      key: 3,
+    },
+    {
+      label: '曲晨一',
+      value: '[email protected]',
+      abbr: '一',
+      color: 'blue',
+      area: 'India',
+      key: 4,
+    },
+    {
+      label: '曲晨二',
+      value: '[email protected]',
+      abbr: '二',
+      color: 'blue',
+      area: 'India',
+      key: 5,
+    },
+    {
+      label: '曲晨三',
+      value: '[email protected]',
+      abbr: '三',
+      color: 'blue',
+      area: 'India',
+      key: 6,
+    },
+  ];
+
+  const renderSourceItem = item => {
+    return (
+      <div className="components-transfer-demo-source-item">
+        <Checkbox
+          onChange={() => {
+            item.onChange();
+          }}
+          key={item.label}
+          checked={item.checked}
+          style={{ paddingLeft: 12, height: 52 }}
+        >
+          <Avatar color={item.color} size="small">
+            {item.abbr}
+          </Avatar>
+          <div className="info">
+            <div className="name">{item.label}</div>
+            <div className="email">{item.value}</div>
+          </div>
+        </Checkbox>
+      </div>
+    );
+  };
+  const renderSelectedItem = item => {
     return (
-        <div style={{ margin: 10, padding: 10, width: 600 }}>
-            <Transfer
-                {...commonProps}
-                dataSource={data}
-                filter={customFilter}
-                defaultValue={['[email protected]']}
-                renderSelectedItem={renderSelectedItem}
-                renderSourceItem={renderSourceItem}
-                inputProps={{ placeholder: '可通过邮箱或者姓名搜索' }}
-            />
+      <div className="components-transfer-demo-selected-item" key={item.label}>
+        <Avatar color={item.color} size="small">
+          {item.abbr}
+        </Avatar>
+        <div className="info">
+          <div className="name">{item.label}</div>
+          <div className="email">{item.value}</div>
         </div>
+        <IconClose onClick={item.onRemove} />
+      </div>
     );
-});
+  };
+  return (
+    <div style={{ margin: 10, padding: 10, width: 600 }}>
+      <Transfer
+        {...commonProps}
+        dataSource={data}
+        filter={customFilter}
+        defaultValue={['[email protected]']}
+        renderSelectedItem={renderSelectedItem}
+        renderSourceItem={renderSourceItem}
+        inputProps={{ placeholder: '可通过邮箱或者姓名搜索' }}
+      />
+    </div>
+  );
+};
+
+CustomFilterRenderSourceItemRenderSelectedItem.story = {
+  name: 'custom filter, renderSourceItem, renderSelectedItem',
+};
 
 const TreeTransferDemo = () => {
-    const treeData = [
+  const treeData = [
+    {
+      label: 'Asia',
+      value: 'Asia',
+      key: '0',
+      children: [
+        {
+          label: 'China',
+          value: 'China',
+          key: '0-0',
+          children: [
+            {
+              label: 'Beijing',
+              value: 'Beijing',
+              key: '0-0-0',
+              disabled: true,
+            },
+            {
+              label: 'ShanghaionChangeonChangeonChange',
+              value: 'Shanghai',
+              key: '0-0-1',
+            },
+            {
+              label: 'Chengdu',
+              value: 'Chengdu',
+              key: '0-0-2',
+            },
+            {
+              label: 'Chongqing',
+              value: 'Chongqing',
+              key: '0-0-3',
+            },
+          ],
+        },
         {
-            label: 'Asia',
-            value: 'Asia',
-            key: '0',
-            children: [
-                {
-                    label: 'China',
-                    value: 'China',
-                    key: '0-0',
-                    children: [
-                        {
-                            label: 'Beijing',
-                            value: 'Beijing',
-                            key: '0-0-0',
-                            disabled: true,
-                        },
-                        {
-                            label: 'ShanghaionChangeonChangeonChange',
-                            value: 'Shanghai',
-                            key: '0-0-1',
-                        },
-                        {
-                            label: 'Chengdu',
-                            value: 'Chengdu',
-                            key: '0-0-2',
-                        },
-                        {
-                            label: 'Chongqing',
-                            value: 'Chongqing',
-                            key: '0-0-3',
-                        },
-                    ],
-                },
-                {
-                    label: 'Japan',
-                    value: 'Japan',
-                    key: '0-1',
-                    children: [
-                        {
-                            label: 'Osaka',
-                            value: 'Osaka',
-                            key: '0-1-0',
-                        },
-                    ],
-                },
-            ],
+          label: 'Japan',
+          value: 'Japan',
+          key: '0-1',
+          children: [
+            {
+              label: 'Osaka',
+              value: 'Osaka',
+              key: '0-1-0',
+            },
+          ],
         },
+      ],
+    },
+    {
+      label: 'North America',
+      value: 'North America',
+      key: '1',
+      children: [
         {
-            label: 'North America',
-            value: 'North America',
-            key: '1',
-            children: [
-                {
-                    label: 'United States',
-                    value: 'United States',
-                    key: '1-0',
-                },
-                {
-                    label: 'Canada',
-                    value: 'Canada',
-                    key: '1-1',
-                },
-            ],
+          label: 'United States',
+          value: 'United States',
+          key: '1-0',
         },
-    ];
-    const [value, $value] = useState(['Shanghai']);
-
-    const onSearch = v => {
-        console.log(v);
-    };
-    const onChange = v => {
-        console.log(v);
-        $value(v);
-    };
-
-    const flatTreeData = dataSource => {
-        let newData = [];
-        let stack = [...dataSource].reverse();
-        while (stack.length) {
-            const current = stack.pop();
-            if (current.children && Array.isArray(current.children)) {
-                const nodes = current.children;
-                for (let i = nodes.length - 1; i >= 0; i--) {
-                    const child = { ...nodes[i] };
-                    stack.push(child);
-                }
-            } else {
-                current.isLeaf = true;
-            }
-            newData.push(omit(current, ['children']));
+        {
+          label: 'Canada',
+          value: 'Canada',
+          key: '1-1',
+        },
+      ],
+    },
+  ];
+  const [value, $value] = useState(['Shanghai']);
+
+  const onSearch = v => {
+    console.log(v);
+  };
+  const onChange = v => {
+    console.log(v);
+    $value(v);
+  };
+
+  const flatTreeData = dataSource => {
+    let newData = [];
+    let stack = [...dataSource].reverse();
+    while (stack.length) {
+      const current = stack.pop();
+      if (current.children && Array.isArray(current.children)) {
+        const nodes = current.children;
+        for (let i = nodes.length - 1; i >= 0; i--) {
+          const child = { ...nodes[i] };
+          stack.push(child);
         }
-        return newData;
-    };
-
-    const flatNodes = flatTreeData(treeData);
+      } else {
+        current.isLeaf = true;
+      }
+      newData.push(omit(current, ['children']));
+    }
+    return newData;
+  };
 
-    const renderSourcePanel = ({ value, onSelect }) => {
-        return (
-            <section style={{ width: '50%' }}>
-                <Tree
-                    defaultExpandAll
-                    multiple
-                    treeData={treeData}
-                    disableStrictly
-                    value={value}
-                    onChange={onSelect}
-                ></Tree>
-            </section>
-        );
-    };
+  const flatNodes = flatTreeData(treeData);
 
+  const renderSourcePanel = ({ value, onSelect }) => {
     return (
-        <div style={{ margin: 10, padding: 10, width: 600 }}>
-            <Transfer
-                type="treeList"
-                draggable
-                dataSource={treeData}
-                value={value}
-                onChange={onChange}
-                onSearch={onSearch}
-            ></Transfer>
-            <Transfer
-                type="treeList"
-                draggable
-                dataSource={treeData}
-                value={value}
-                renderSourcePanel={renderSourcePanel}
-                onChange={onChange}
-                onSearch={onSearch}
-            ></Transfer>
-        </div>
+      <section style={{ width: '50%' }}>
+        <Tree
+          defaultExpandAll
+          multiple
+          treeData={treeData}
+          disableStrictly
+          value={value}
+          onChange={onSelect}
+        ></Tree>
+      </section>
     );
+  };
+
+  return (
+    <div style={{ margin: 10, padding: 10, width: 600 }}>
+      <Transfer
+        type="treeList"
+        draggable
+        dataSource={treeData}
+        value={value}
+        onChange={onChange}
+        onSearch={onSearch}
+      ></Transfer>
+      <Transfer
+        type="treeList"
+        draggable
+        dataSource={treeData}
+        value={value}
+        renderSourcePanel={renderSourcePanel}
+        onChange={onChange}
+        onSearch={onSearch}
+      ></Transfer>
+    </div>
+  );
 };
 
-stories.add('tree transfer', () => <TreeTransferDemo />);
+export const TreeTransfer = () => <TreeTransferDemo />;
 
-class CustomRenderDemo extends React.Component {
-    constructor(props) {
-        super(props);
-        this.state = {
-            dataSource: Array.from({ length: 100 }, (v, i) => ({
-                label: `海底捞门店 ${i}`,
-                value: i,
-                disabled: false,
-                key: i,
-            })),
-        };
-        this.renderSourcePanel = this.renderSourcePanel.bind(this);
-        this.renderSelectedPanel = this.renderSelectedPanel.bind(this);
-        this.renderItem = this.renderItem.bind(this);
-    }
+TreeTransfer.story = {
+  name: 'tree transfer',
+};
 
-    renderItem(type, item, onItemAction, selectedItems) {
-        let buttonText = '删除';
-        if (type === 'source') {
-            let checked = selectedItems.has(item.key);
-            buttonText = checked ? '删除' : '添加';
-        }
-        return (
-            <div className="semi-transfer-item panel-item" key={item.label}>
-                <p>{item.label}</p>
-                <Button
-                    theme="borderless"
-                    type="primary"
-                    onClick={() => onItemAction(item)}
-                    className="panel-item-remove"
-                    size="small"
-                >
-                    {buttonText}
-                </Button>
-            </div>
-        );
+class CustomRenderDemo extends React.Component {
+  constructor(props) {
+    super(props);
+    this.state = {
+      dataSource: Array.from({ length: 100 }, (v, i) => ({
+        label: `海底捞门店 ${i}`,
+        value: i,
+        disabled: false,
+        key: i,
+      })),
+    };
+    this.renderSourcePanel = this.renderSourcePanel.bind(this);
+    this.renderSelectedPanel = this.renderSelectedPanel.bind(this);
+    this.renderItem = this.renderItem.bind(this);
+  }
+
+  renderItem(type, item, onItemAction, selectedItems) {
+    let buttonText = '删除';
+    if (type === 'source') {
+      let checked = selectedItems.has(item.key);
+      buttonText = checked ? '删除' : '添加';
     }
-
-    renderSourcePanel(props) {
-        const {
-            loading,
-            noMatch,
-            filterData,
-            selectedItems,
-            allChecked,
-            onAllClick,
-            inputValue,
-            onSearch,
-            onSelectOrRemove,
-        } = props;
-        let content;
-        switch (true) {
-            case loading:
-                content = <Spin loading />;
-                break;
-            case noMatch:
-                content = <div className="empty sp-font">{inputValue ? '无搜索结果' : '暂无内容'}</div>;
-                break;
-            case !noMatch:
-                content = filterData.map(item => this.renderItem('source', item, onSelectOrRemove, selectedItems));
-                break;
-            default:
-                content = null;
-                break;
-        }
-        return (
-            <section className="source-panel">
-                <div className="panel-header sp-font">门店列表</div>
-                <div className="panel-main">
-                    <Input
-                        style={{ width: 454, margin: '12px 14px' }}
-                        prefix={<IconSearch />}
-                        onChange={onSearch}
-                        showClear
-                    />
-                    <div className="panel-controls sp-font">
-                        <span>待选门店: {filterData.length}</span>
-                        <Button onClick={onAllClick} theme="borderless" size="small">
-                            {allChecked ? '取消全选' : '全选'}
-                        </Button>
-                    </div>
-                    <div className="panel-list">{content}</div>
-                </div>
-            </section>
+    return (
+      <div className="semi-transfer-item panel-item" key={item.label}>
+        <p>{item.label}</p>
+        <Button
+          theme="borderless"
+          type="primary"
+          onClick={() => onItemAction(item)}
+          className="panel-item-remove"
+          size="small"
+        >
+          {buttonText}
+        </Button>
+      </div>
+    );
+  }
+
+  renderSourcePanel(props) {
+    const {
+      loading,
+      noMatch,
+      filterData,
+      selectedItems,
+      allChecked,
+      onAllClick,
+      inputValue,
+      onSearch,
+      onSelectOrRemove,
+    } = props;
+    let content;
+    switch (true) {
+      case loading:
+        content = <Spin loading />;
+        break;
+      case noMatch:
+        content = <div className="empty sp-font">{inputValue ? '无搜索结果' : '暂无内容'}</div>;
+        break;
+      case !noMatch:
+        content = filterData.map(item =>
+          this.renderItem('source', item, onSelectOrRemove, selectedItems)
         );
+        break;
+      default:
+        content = null;
+        break;
     }
+    return (
+      <section className="source-panel">
+        <div className="panel-header sp-font">门店列表</div>
+        <div className="panel-main">
+          <Input
+            style={{ width: 454, margin: '12px 14px' }}
+            prefix={<IconSearch />}
+            onChange={onSearch}
+            showClear
+          />
+          <div className="panel-controls sp-font">
+            <span>待选门店: {filterData.length}</span>
+            <Button onClick={onAllClick} theme="borderless" size="small">
+              {allChecked ? '取消全选' : '全选'}
+            </Button>
+          </div>
+          <div className="panel-list">{content}</div>
+        </div>
+      </section>
+    );
+  }
 
-    renderSelectedPanel(props) {
-        const { selectedData, onClear, clearText, onRemove } = props;
+  renderSelectedPanel(props) {
+    const { selectedData, onClear, clearText, onRemove } = props;
 
-        let mainContent = selectedData.map(item => this.renderItem('selected', item, onRemove));
+    let mainContent = selectedData.map(item => this.renderItem('selected', item, onRemove));
 
-        if (!selectedData.length) {
-            mainContent = <div className="empty sp-font">暂无数据,请从左侧筛选</div>;
-        }
-
-        return (
-            <section className="selected-panel">
-                <div className="panel-header sp-font">
-                    <div>已选同步门店: {selectedData.length}</div>
-                    <Button theme="borderless" type="primary" onClick={onClear} size="small">
-                        {clearText || '清空 '}
-                    </Button>
-                </div>
-                <div className="panel-main">{mainContent}</div>
-            </section>
-        );
+    if (!selectedData.length) {
+      mainContent = <div className="empty sp-font">暂无数据,请从左侧筛选</div>;
     }
 
-    render() {
-        const { dataSource } = this.state;
-        return (
-            <Transfer
-                onChange={values => console.log(values)}
-                className="component-transfer-demo-custom-panel"
-                renderSourcePanel={this.renderSourcePanel}
-                renderSelectedPanel={this.renderSelectedPanel}
-                dataSource={dataSource}
-            />
-        );
-    }
+    return (
+      <section className="selected-panel">
+        <div className="panel-header sp-font">
+          <div>已选同步门店: {selectedData.length}</div>
+          <Button theme="borderless" type="primary" onClick={onClear} size="small">
+            {clearText || '清空 '}
+          </Button>
+        </div>
+        <div className="panel-main">{mainContent}</div>
+      </section>
+    );
+  }
+
+  render() {
+    const { dataSource } = this.state;
+    return (
+      <Transfer
+        onChange={values => console.log(values)}
+        className="component-transfer-demo-custom-panel"
+        renderSourcePanel={this.renderSourcePanel}
+        renderSelectedPanel={this.renderSelectedPanel}
+        dataSource={dataSource}
+      />
+    );
+  }
 }
 
-stories.add('customRender', () => <CustomRenderDemo />);
+export const CustomRender = () => <CustomRenderDemo />;
+
+CustomRender.story = {
+  name: 'customRender',
+};
 
 class CustomRenderDragDemo extends React.Component {
-    constructor(props) {
-        super(props);
-        this.state = {
-            dataSource: Array.from({ length: 100 }, (v, i) => ({
-                label: `海底捞门店 ${i}`,
-                value: i,
-                disabled: false,
-                key: i,
-            })),
-        };
-        this.renderSourcePanel = this.renderSourcePanel.bind(this);
-        this.renderSelectedPanel = this.renderSelectedPanel.bind(this);
-        this.renderItem = this.renderItem.bind(this);
+  constructor(props) {
+    super(props);
+    this.state = {
+      dataSource: Array.from({ length: 100 }, (v, i) => ({
+        label: `海底捞门店 ${i}`,
+        value: i,
+        disabled: false,
+        key: i,
+      })),
+    };
+    this.renderSourcePanel = this.renderSourcePanel.bind(this);
+    this.renderSelectedPanel = this.renderSelectedPanel.bind(this);
+    this.renderItem = this.renderItem.bind(this);
+  }
+
+  renderItem(type, item, onItemAction, selectedItems) {
+    let buttonText = '删除';
+    let newItem = item;
+
+    if (type === 'source') {
+      let checked = selectedItems.has(item.key);
+      buttonText = checked ? '删除' : '添加';
+    } else {
+      // delete newItem._optionKey;
+      newItem = { ...item, key: item._optionKey };
+      delete newItem._optionKey;
     }
 
-    renderItem(type, item, onItemAction, selectedItems) {
-        let buttonText = '删除';
-        let newItem = item;
-
-        if (type === 'source') {
-            let checked = selectedItems.has(item.key);
-            buttonText = checked ? '删除' : '添加';
-        } else {
-            // delete newItem._optionKey;
-            newItem = { ...item, key: item._optionKey };
-            delete newItem._optionKey;
-        }
-
-        const DragHandle = sortableHandle(() => <IconHandle className="pane-item-drag-handler" />);
+    const DragHandle = sortableHandle(() => <IconHandle className="pane-item-drag-handler" />);
 
-        return (
-            <div className="semi-transfer-item panel-item" key={item.label}>
-                {type === 'source' ? null : <DragHandle />}
-                <div className="panel-item-main" style={{ flexGrow: 1 }}>
-                    <p>{item.label}</p>
-                    <Button
-                        theme="borderless"
-                        type="primary"
-                        onClick={() => onItemAction(newItem)}
-                        className="panel-item-remove"
-                        size="small"
-                    >
-                        {buttonText}
-                    </Button>
-                </div>
-            </div>
-        );
-    }
-
-    renderSourcePanel(props) {
-        const {
-            loading,
-            noMatch,
-            filterData,
-            selectedItems,
-            allChecked,
-            onAllClick,
-            inputValue,
-            onSearch,
-            onSelectOrRemove,
-        } = props;
-        let content;
-        switch (true) {
-            case loading:
-                content = <Spin loading />;
-                break;
-            case noMatch:
-                content = <div className="empty sp-font">{inputValue ? '无搜索结果' : '暂无内容'}</div>;
-                break;
-            case !noMatch:
-                content = filterData.map(item => this.renderItem('source', item, onSelectOrRemove, selectedItems));
-                break;
-            default:
-                content = null;
-                break;
-        }
-        return (
-            <section className="source-panel">
-                <div className="panel-header sp-font">门店列表</div>
-                <div className="panel-main">
-                    <Input
-                        style={{ width: 454, margin: '12px 14px' }}
-                        prefix={<IconSearch />}
-                        onChange={onSearch}
-                        showClear
-                    />
-                    <div className="panel-controls sp-font">
-                        <span>待选门店: {filterData.length}</span>
-                        <Button onClick={onAllClick} theme="borderless" size="small">
-                            {allChecked ? '取消全选' : '全选'}
-                        </Button>
-                    </div>
-                    <div className="panel-list">{content}</div>
-                </div>
-            </section>
+    return (
+      <div className="semi-transfer-item panel-item" key={item.label}>
+        {type === 'source' ? null : <DragHandle />}
+        <div className="panel-item-main" style={{ flexGrow: 1 }}>
+          <p>{item.label}</p>
+          <Button
+            theme="borderless"
+            type="primary"
+            onClick={() => onItemAction(newItem)}
+            className="panel-item-remove"
+            size="small"
+          >
+            {buttonText}
+          </Button>
+        </div>
+      </div>
+    );
+  }
+
+  renderSourcePanel(props) {
+    const {
+      loading,
+      noMatch,
+      filterData,
+      selectedItems,
+      allChecked,
+      onAllClick,
+      inputValue,
+      onSearch,
+      onSelectOrRemove,
+    } = props;
+    let content;
+    switch (true) {
+      case loading:
+        content = <Spin loading />;
+        break;
+      case noMatch:
+        content = <div className="empty sp-font">{inputValue ? '无搜索结果' : '暂无内容'}</div>;
+        break;
+      case !noMatch:
+        content = filterData.map(item =>
+          this.renderItem('source', item, onSelectOrRemove, selectedItems)
         );
+        break;
+      default:
+        content = null;
+        break;
     }
+    return (
+      <section className="source-panel">
+        <div className="panel-header sp-font">门店列表</div>
+        <div className="panel-main">
+          <Input
+            style={{ width: 454, margin: '12px 14px' }}
+            prefix={<IconSearch />}
+            onChange={onSearch}
+            showClear
+          />
+          <div className="panel-controls sp-font">
+            <span>待选门店: {filterData.length}</span>
+            <Button onClick={onAllClick} theme="borderless" size="small">
+              {allChecked ? '取消全选' : '全选'}
+            </Button>
+          </div>
+          <div className="panel-list">{content}</div>
+        </div>
+      </section>
+    );
+  }
 
-    renderSelectedPanel(props) {
-        const { selectedData, onClear, clearText, onRemove, onSortEnd } = props;
+  renderSelectedPanel(props) {
+    const { selectedData, onClear, clearText, onRemove, onSortEnd } = props;
 
-        let mainContent = null;
+    let mainContent = null;
 
-        if (!selectedData.length) {
-            mainContent = <div className="empty sp-font">暂无数据,请从左侧筛选</div>;
-        }
+    if (!selectedData.length) {
+      mainContent = <div className="empty sp-font">暂无数据,请从左侧筛选</div>;
+    }
 
-        const SortableItem = SortableElement(item => this.renderItem('selected', item, onRemove));
-        const SortableList = SortableContainer(
-            ({ items }) => {
-                return (
-                    <div className="panel-main">
-                        {items.map((item, index) => (
-                            // sortableElement will take over the property 'key', so use another '_optionKey' to pass
-                            // otherwise you can't get `key` property in this.renderItem
-                            <SortableItem key={item.label} index={index} {...item} _optionKey={item.key}></SortableItem>
-                        ))}
-                    </div>
-                );
-            },
-            { distance: 10 }
+    const SortableItem = SortableElement(item => this.renderItem('selected', item, onRemove));
+    const SortableList = SortableContainer(
+      ({ items }) => {
+        return (
+          <div className="panel-main">
+            {items.map((item, index) => (
+              // sortableElement will take over the property 'key', so use another '_optionKey' to pass
+              // otherwise you can't get `key` property in this.renderItem
+              <SortableItem
+                key={item.label}
+                index={index}
+                {...item}
+                _optionKey={item.key}
+              ></SortableItem>
+            ))}
+          </div>
         );
+      },
+      { distance: 10 }
+    );
 
-        mainContent = <SortableList useDragHandle onSortEnd={onSortEnd} items={selectedData}></SortableList>;
+    mainContent = (
+      <SortableList useDragHandle onSortEnd={onSortEnd} items={selectedData}></SortableList>
+    );
 
-        return (
-            <section className="selected-panel">
-                <div className="panel-header sp-font">
-                    <div>已选同步门店: {selectedData.length}</div>
-                    <Button theme="borderless" type="primary" onClick={onClear} size="small">
-                        {clearText || '清空 '}
-                    </Button>
-                </div>
-                {mainContent}
-            </section>
-        );
-    }
+    return (
+      <section className="selected-panel">
+        <div className="panel-header sp-font">
+          <div>已选同步门店: {selectedData.length}</div>
+          <Button theme="borderless" type="primary" onClick={onClear} size="small">
+            {clearText || '清空 '}
+          </Button>
+        </div>
+        {mainContent}
+      </section>
+    );
+  }
 
-    render() {
-        const { dataSource } = this.state;
-        return (
-            <Transfer
-                defaultValue={[2, 4]}
-                onChange={values => console.log(values)}
-                className="component-transfer-demo-custom-panel"
-                renderSourcePanel={this.renderSourcePanel}
-                renderSelectedPanel={this.renderSelectedPanel}
-                dataSource={dataSource}
-            />
-        );
-    }
+  render() {
+    const { dataSource } = this.state;
+    return (
+      <Transfer
+        defaultValue={[2, 4]}
+        onChange={values => console.log(values)}
+        className="component-transfer-demo-custom-panel"
+        renderSourcePanel={this.renderSourcePanel}
+        renderSelectedPanel={this.renderSelectedPanel}
+        dataSource={dataSource}
+      />
+    );
+  }
 }
 
-stories.add('customRender with drag sort', () => <CustomRenderDragDemo />);
+export const CustomRenderWithDragSort = () => <CustomRenderDragDemo />;
+
+CustomRenderWithDragSort.story = {
+  name: 'customRender with drag sort',
+};

+ 1954 - 1800
packages/semi-ui/tree/_story/tree.stories.js

@@ -1,2018 +1,2172 @@
-import React, {useRef, useState} from 'react';
-import {storiesOf} from '@storybook/react';
+import React, { useRef, useState } from 'react';
 import Tree from '../index';
 import AutoSizer from '../autoSizer';
-import {Button, ButtonGroup, Input, Popover, Toast} from '../../index';
+import { Button, ButtonGroup, Input, Popover, Toast } from '../../index';
 import BigTree from './BigData';
 import testData from './data';
-import {cloneDeep, difference, isEqual,} from 'lodash-es';
-import {IconEdit, IconMapPin, IconMore} from '@douyinfe/semi-icons';
+import { cloneDeep, difference, isEqual } from 'lodash-es';
+import { IconEdit, IconMapPin, IconMore } from '@douyinfe/semi-icons';
 
 const TreeNode = Tree.TreeNode;
 
-const stories = storiesOf('Tree', module);
+export default {
+  title: 'Tree'
+}
 
 const treeChildren = [
-    {
-        label: '北京',
-        value: 'beijing',
-        key: 'beijing',
-    },
-    {
-        label: '上海',
-        value: 'shanghai',
-        key: 'shanghai',
-    },
+  {
+    label: '北京',
+    value: 'beijing',
+    key: 'beijing',
+  },
+  {
+    label: '上海',
+    value: 'shanghai',
+    key: 'shanghai',
+  },
 ];
 
 const treeData1 = [
-    {
-        label: '亚洲',
-        value: 'yazhou',
-        key: 'yazhou',
-        children: [
-            {
-                label: '中国',
-                value: 'zhongguo',
-                key: 'zhongguo',
-                disabled: true,
-                children: treeChildren,
-            },
-            {
-                label: '日本',
-                value: 'riben',
-                key: 'riben',
-                children: [
-                    {
-                        label: '东京',
-                        value: 'dongjing',
-                        key: 'dongjing',
-                    },
-                    {
-                        label: '大阪',
-                        value: 'daban',
-                        key: 'daban',
-                    },
-                ],
-            },
-        ],
-    },
-    {
-        label: '北美洲',
-        value: 'beimeizhou',
-        key: 'beimeizhou',
+  {
+    label: '亚洲',
+    value: 'yazhou',
+    key: 'yazhou',
+    children: [
+      {
+        label: '中国',
+        value: 'zhongguo',
+        key: 'zhongguo',
+        disabled: true,
+        children: treeChildren,
+      },
+      {
+        label: '日本',
+        value: 'riben',
+        key: 'riben',
         children: [
-            {
-                label: '美国',
-                value: 'meiguo',
-                key: 'meiguo',
-            },
-            {
-                label: '加拿大',
-                value: 'jianada',
-                key: 'jianada',
-            },
+          {
+            label: '东京',
+            value: 'dongjing',
+            key: 'dongjing',
+          },
+          {
+            label: '大阪',
+            value: 'daban',
+            key: 'daban',
+          },
         ],
-    },
+      },
+    ],
+  },
+  {
+    label: '北美洲',
+    value: 'beimeizhou',
+    key: 'beimeizhou',
+    children: [
+      {
+        label: '美国',
+        value: 'meiguo',
+        key: 'meiguo',
+      },
+      {
+        label: '加拿大',
+        value: 'jianada',
+        key: 'jianada',
+      },
+    ],
+  },
 ];
 
 const treeDataWithoutValue = [
-    {
-        label: '亚洲',
-        key: 'yazhou',
-        children: [
-            {
-                label: '中国',
-                key: 'zhongguo',
-                disabled: true,
-                children: treeChildren,
-            },
-            {
-                label: '日本',
-                key: 'riben',
-                children: [
-                    {
-                        label: '东京',
-                        key: 'dongjing',
-                    },
-                    {
-                        label: '大阪',
-                        key: 'daban',
-                    },
-                ],
-            },
-        ],
-    },
-    {
-        label: '北美洲',
-        key: 'beimeizhou',
+  {
+    label: '亚洲',
+    key: 'yazhou',
+    children: [
+      {
+        label: '中国',
+        key: 'zhongguo',
+        disabled: true,
+        children: treeChildren,
+      },
+      {
+        label: '日本',
+        key: 'riben',
         children: [
-            {
-                label: '美国',
-                key: 'meiguo',
-            },
-            {
-                label: '加拿大',
-                key: 'jianada',
-            },
+          {
+            label: '东京',
+            key: 'dongjing',
+          },
+          {
+            label: '大阪',
+            key: 'daban',
+          },
         ],
-    },
+      },
+    ],
+  },
+  {
+    label: '北美洲',
+    key: 'beimeizhou',
+    children: [
+      {
+        label: '美国',
+        key: 'meiguo',
+      },
+      {
+        label: '加拿大',
+        key: 'jianada',
+      },
+    ],
+  },
 ];
 
 const treeDataWithIcon = [
-    {
-        label: 'Asia',
-        value: 'Asia',
-        key: '0',
-        icon: <IconMapPin style={{color: 'var(--semi-color-text-2)'}}/>,
-        children: [
-            {
-                label: 'China',
-                value: 'China',
-                key: '0-0',
-                icon: <IconMapPin style={{color: 'var(--semi-color-text-2)'}}/>,
-            },
-            {
-                label: 'Japan',
-                value: 'Japan',
-                key: '0-1',
-                icon: <IconMapPin style={{color: 'var(--semi-color-text-2)'}}/>,
-            },
-        ],
-    },
+  {
+    label: 'Asia',
+    value: 'Asia',
+    key: '0',
+    icon: <IconMapPin style={{ color: 'var(--semi-color-text-2)' }} />,
+    children: [
+      {
+        label: 'China',
+        value: 'China',
+        key: '0-0',
+        icon: <IconMapPin style={{ color: 'var(--semi-color-text-2)' }} />,
+      },
+      {
+        label: 'Japan',
+        value: 'Japan',
+        key: '0-1',
+        icon: <IconMapPin style={{ color: 'var(--semi-color-text-2)' }} />,
+      },
+    ],
+  },
 ];
 
 let opts = {
-    content: 'Hi, Bytedance dance dance',
-    duration: 3,
+  content: 'Hi, Bytedance dance dance',
+  duration: 3,
 };
 
 const treeDataWithNode = [
-    {
-        label: (
-            <span>
-                <span style={{marginRight: 30}}>亚洲</span>
-                <Button
-                    style={{zIndex: 2}}
-                    onClick={e => {
-                        Toast.info(opts);
-                        e.stopPropagation();
-                    }}
-                >
-                    Display Toast
-                </Button>
-            </span>
-        ),
-        value: 'yazhou',
-        key: 'yazhou',
-        children: [
-            {
-                label: '中国',
-                value: 'zhongguo',
-                key: 'zhongguo',
-                children: [
-                    {
-                        label: '北京',
-                        value: 'beijing',
-                        key: 'beijing',
-                    },
-                    {
-                        label: '上海',
-                        value: 'shanghai',
-                        key: 'shanghai',
-                    },
-                ],
-            },
-            {
-                label: '日本',
-                value: 'riben',
-                key: 'riben',
-            },
-        ],
-    },
-    {
-        label: '北美洲',
-        value: 'beimeizhou',
-        key: 'beimeizhou',
+  {
+    label: (
+      <span>
+        <span style={{ marginRight: 30 }}>亚洲</span>
+        <Button
+          style={{ zIndex: 2 }}
+          onClick={e => {
+            Toast.info(opts);
+            e.stopPropagation();
+          }}
+        >
+          Display Toast
+        </Button>
+      </span>
+    ),
+    value: 'yazhou',
+    key: 'yazhou',
+    children: [
+      {
+        label: '中国',
+        value: 'zhongguo',
+        key: 'zhongguo',
         children: [
-            {
-                label: '美国',
-                value: 'meiguo',
-                key: 'meiguo',
-            },
-            {
-                label: '加拿大',
-                value: 'jianada',
-                key: 'jianada',
-            },
+          {
+            label: '北京',
+            value: 'beijing',
+            key: 'beijing',
+          },
+          {
+            label: '上海',
+            value: 'shanghai',
+            key: 'shanghai',
+          },
         ],
-    },
+      },
+      {
+        label: '日本',
+        value: 'riben',
+        key: 'riben',
+      },
+    ],
+  },
+  {
+    label: '北美洲',
+    value: 'beimeizhou',
+    key: 'beimeizhou',
+    children: [
+      {
+        label: '美国',
+        value: 'meiguo',
+        key: 'meiguo',
+      },
+      {
+        label: '加拿大',
+        value: 'jianada',
+        key: 'jianada',
+      },
+    ],
+  },
 ];
 
 const treeJson = {
-    Node1: {
-        Child1: '0-0-1',
-        Child2: '0-0-2',
-    },
-    Node2: '0-1',
+  Node1: {
+    Child1: '0-0-1',
+    Child2: '0-0-2',
+  },
+  Node2: '0-1',
 };
 
 const benchmarkSet = size => {
-    console.time('benchmarkSet');
-    var set = new Set();
-    for (var i = 0; i < size; i++) set.add(i);
-    for (var i = 0; i < size; i++) set.has(i);
-    console.timeEnd('benchmarkSet');
+  console.time('benchmarkSet');
+  var set = new Set();
+  for (var i = 0; i < size; i++) set.add(i);
+  for (var i = 0; i < size; i++) set.has(i);
+  console.timeEnd('benchmarkSet');
 };
 
 const benchmarkArr = size => {
-    console.time('benchmarkArr');
-    var arr = [];
-    for (var i = 0; i < size; i++) arr.push(i);
-    for (var i = 0; i < size; i++) arr.indexOf(i);
-    console.timeEnd('benchmarkArr');
+  console.time('benchmarkArr');
+  var arr = [];
+  for (var i = 0; i < size; i++) arr.push(i);
+  for (var i = 0; i < size; i++) arr.indexOf(i);
+  console.timeEnd('benchmarkArr');
 };
 
-stories.add('bench mark', () => {
-    const size = 100000;
-    benchmarkSet(size);
-    benchmarkArr(size);
-    return <div>check console please</div>;
-});
+export const BenchMark = () => {
+  const size = 100000;
+  benchmarkSet(size);
+  benchmarkArr(size);
+  return <div>check console please</div>;
+};
 
-stories.add('simple tree', () => (
-    <Tree
-        treeData={treeData1}
-        // onExpand={(e, { expanded, node }) => console.log('expand', e, expanded, node)}
-        // onSelect={(e, bool, node) => console.log('select', e, bool, node)}
-        // onChange={e => console.log('change', e)}
-        onRightClick={(e, node) => console.log(e.currentTarget, node)}
-        onDoubleClick={(e, node) => console.log(e, node)}
-        motion={true}
-    />
-));
+BenchMark.story = {
+  name: 'bench mark',
+};
+
+export const SimpleTree = () => (
+  <Tree
+    treeData={treeData1}
+    // onExpand={(e, { expanded, node }) => console.log('expand', e, expanded, node)}
+    // onSelect={(e, bool, node) => console.log('select', e, bool, node)}
+    // onChange={e => console.log('change', e)}
+    onRightClick={(e, node) => console.log(e.currentTarget, node)}
+    onDoubleClick={(e, node) => console.log(e, node)}
+    motion={true}
+  />
+);
+
+SimpleTree.story = {
+  name: 'simple tree',
+};
+
+export const MultipleTree = () => (
+  <Tree
+    treeData={treeData1}
+    multiple
+    labelInValue
+    // onExpand={(e, { expanded, node }) => console.log('expand', e, expanded, node)}
+    // onSelect={(e, bool) => console.log('select', e, bool)}
+    onRightClick={(e, node) => console.log(e, node)}
+    onDoubleClick={(e, node) => console.log(e, node)}
+    onChange={e => console.log('change', e)}
+  />
+);
+
+MultipleTree.story = {
+  name: 'multiple tree',
+};
+
+export const SearchableTree = () => (
+  <Tree
+    treeData={treeData1}
+    filterTreeNode
+    treeNodeFilterProp="value"
+    multiple
+    searchStyle={{ width: '300px' }}
+  />
+);
 
-stories.add('multiple tree', () => (
+SearchableTree.story = {
+  name: 'searchable tree',
+};
+
+export const DisabledTree = () => (
+  <Tree treeData={treeData1} defaultValue={['dongjing', 'daban']} multiple disabled />
+);
+
+DisabledTree.story = {
+  name: 'disabled tree',
+};
+
+export const DefaultTree = () => (
+  <div>
+    <Tree treeData={treeData1} defaultValue={['zhongguo']} />
+    <br />
     <Tree
-        treeData={treeData1}
-        multiple
-        labelInValue
-        // onExpand={(e, { expanded, node }) => console.log('expand', e, expanded, node)}
-        // onSelect={(e, bool) => console.log('select', e, bool)}
-        onRightClick={(e, node) => console.log(e, node)}
-        onDoubleClick={(e, node) => console.log(e, node)}
-        onChange={e => console.log('change', e)}
+      treeData={treeData1}
+      multiple
+      defaultValue={['shanghai', 'dongjing', 'beijing', 'daban']}
+      onChange={e => console.log(e)}
+      onSelect={e => console.log(e)}
     />
-));
-
-stories.add('searchable tree', () => (
-    <Tree treeData={treeData1} filterTreeNode treeNodeFilterProp="value" multiple searchStyle={{width: '300px'}}/>
-));
+  </div>
+);
 
-stories.add('disabled tree', () => (
-    <Tree treeData={treeData1} defaultValue={['dongjing', 'daban']} multiple disabled/>
-));
+DefaultTree.story = {
+  name: 'default tree',
+};
 
-stories.add('default tree', () => (
-    <div>
-        <Tree treeData={treeData1} defaultValue={['zhongguo']}/>
-        <br/>
-        <Tree
-            treeData={treeData1}
-            multiple
-            defaultValue={['shanghai', 'dongjing', 'beijing', 'daban']}
-            onChange={e => console.log(e)}
-            onSelect={e => console.log(e)}
-        />
-    </div>
-));
+export const ExpandAction = () => (
+  <div>
+    <Tree treeData={treeData1} defaultValue={['zhongguo']} />
+    <br />
+    <Tree
+      treeData={treeData1}
+      //multiple
+      defaultValue={['shanghai', 'dongjing', 'beijing', 'daban']}
+      expandAction="click"
+      onDoubleClick={e => console.log(e.detail)}
+    />
+    <br />
+    <Tree
+      treeData={treeData1}
+      multiple
+      defaultValue={['shanghai', 'dongjing', 'beijing', 'daban']}
+      expandAction="doubleClick"
+    />
+  </div>
+);
 
-stories.add('expandAction', () => (
-    <div>
-        <Tree treeData={treeData1} defaultValue={['zhongguo']}/>
-        <br/>
-        <Tree
-            treeData={treeData1}
-            //multiple
-            defaultValue={['shanghai', 'dongjing', 'beijing', 'daban']}
-            expandAction="click"
-            onDoubleClick={e => console.log(e.detail)}
-        />
-        <br/>
-        <Tree
-            treeData={treeData1}
-            multiple
-            defaultValue={['shanghai', 'dongjing', 'beijing', 'daban']}
-            expandAction="doubleClick"
-        />
-    </div>
-));
+ExpandAction.story = {
+  name: 'expandAction',
+};
 
 class Demo extends React.Component {
-    constructor() {
-        super();
-        this.state = {
-            value: 'shanghai',
-        };
-    }
+  constructor() {
+    super();
+    this.state = {
+      value: 'shanghai',
+    };
+  }
 
-    onChange(value) {
-        this.setState({value});
-    }
+  onChange(value) {
+    this.setState({ value });
+  }
 
-    render() {
-        return (
-            <Tree
-                style={{width: 300}}
-                dropdownStyle={{maxHeight: 400, overflow: 'auto'}}
-                treeData={treeData1}
-                value={this.state.value}
-                placeholder="Please select"
-                onChange={e => this.onChange(e)}
-            />
-        );
-    }
+  render() {
+    return (
+      <Tree
+        style={{ width: 300 }}
+        dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
+        treeData={treeData1}
+        value={this.state.value}
+        placeholder="Please select"
+        onChange={e => this.onChange(e)}
+      />
+    );
+  }
 }
 
-stories.add('controlled Component single', () => <Demo/>);
+export const ControlledComponentSingle = () => <Demo />;
+
+ControlledComponentSingle.story = {
+  name: 'controlled Component single',
+};
 
 class Demo2 extends React.Component {
-    constructor() {
-        super();
-        this.state = {
-            value: ['shanghai', 'beijing', 'zhongguo'],
-        };
-    }
+  constructor() {
+    super();
+    this.state = {
+      value: ['shanghai', 'beijing', 'zhongguo'],
+    };
+  }
 
-    onChange(value) {
-        console.log(value);
-        this.setState({value});
-    }
+  onChange(value) {
+    console.log(value);
+    this.setState({ value });
+  }
 
-    render() {
-        console.log(this.state.value);
-        return (
-            <Tree
-                style={{width: 300}}
-                multiple
-                dropdownStyle={{maxHeight: 200, overflow: 'auto'}}
-                treeData={treeData1}
-                value={this.state.value}
-                placeholder="Please select"
-                onChange={e => this.onChange(e)}
-            />
-        );
-    }
+  render() {
+    console.log(this.state.value);
+    return (
+      <Tree
+        style={{ width: 300 }}
+        multiple
+        dropdownStyle={{ maxHeight: 200, overflow: 'auto' }}
+        treeData={treeData1}
+        value={this.state.value}
+        placeholder="Please select"
+        onChange={e => this.onChange(e)}
+      />
+    );
+  }
 }
 
-stories.add('controlled Component multiple', () => <Demo2/>);
+export const ControlledComponentMultiple = () => <Demo2 />;
 
-stories.add('json tree', () => (
-    <div>
-        <Tree
-            treeDataSimpleJson={treeJson}
-            onChange={e => console.log('change', e)}
-            onSelect={e => console.log('select', e)}
-        />
-        <br/>
-        <Tree treeDataSimpleJson={treeJson} multiple onChange={e => console.log(e)} onSelect={e => console.log(e)}/>
-    </div>
-));
+ControlledComponentMultiple.story = {
+  name: 'controlled Component multiple',
+};
 
-stories.add('icon tree', () => (
-    <div>
-        <Tree treeData={treeDataWithIcon}/>
-        <br/>
-        <Tree treeData={treeDataWithIcon} multiple blockNode/>
-    </div>
-));
+export const JsonTree = () => (
+  <div>
+    <Tree
+      treeDataSimpleJson={treeJson}
+      onChange={e => console.log('change', e)}
+      onSelect={e => console.log('select', e)}
+    />
+    <br />
+    <Tree
+      treeDataSimpleJson={treeJson}
+      multiple
+      onChange={e => console.log(e)}
+      onSelect={e => console.log(e)}
+    />
+  </div>
+);
+
+JsonTree.story = {
+  name: 'json tree',
+};
+
+export const IconTree = () => (
+  <div>
+    <Tree treeData={treeDataWithIcon} />
+    <br />
+    <Tree treeData={treeDataWithIcon} multiple blockNode />
+  </div>
+);
+
+IconTree.story = {
+  name: 'icon tree',
+};
+
+export const DirectoryTree = () => <Tree treeData={treeData1} directory multiple blockNode />;
 
-stories.add('directory tree', () => <Tree treeData={treeData1} directory multiple blockNode/>);
+DirectoryTree.story = {
+  name: 'directory tree',
+};
 
 const button = (
-    <ButtonGroup size="small" theme="borderless">
-        <Button
-            onClick={e => {
-                Toast.info(opts);
-                e.stopPropagation();
-            }}
-        >
-            提示
-        </Button>
-        <Button>点击</Button>
-    </ButtonGroup>
+  <ButtonGroup size="small" theme="borderless">
+    <Button
+      onClick={e => {
+        Toast.info(opts);
+        e.stopPropagation();
+      }}
+    >
+      提示
+    </Button>
+    <Button>点击</Button>
+  </ButtonGroup>
 );
 
 const style = {
-    display: 'flex',
-    justifyContent: 'space-between',
-    alignItems: 'center',
+  display: 'flex',
+  justifyContent: 'space-between',
+  alignItems: 'center',
 };
 
 const treeDataWithNode2 = [
-    {
+  {
+    label: (
+      <div style={style}>
+        <span>亚洲</span>
+        <ButtonGroup size="small" theme="borderless">
+          {button}
+        </ButtonGroup>
+      </div>
+    ),
+    value: 'yazhou',
+    key: 'yazhou',
+    children: [
+      {
         label: (
-            <div style={style}>
-                <span>亚洲</span>
-                <ButtonGroup size="small" theme="borderless">
-                    {button}
-                </ButtonGroup>
-            </div>
+          <div style={style}>
+            <span>中国</span>
+            {button}
+          </div>
         ),
-        value: 'yazhou',
-        key: 'yazhou',
+        value: 'zhongguo',
+        key: 'zhongguo',
         children: [
-            {
-                label: (
-                    <div style={style}>
-                        <span>中国</span>
-                        {button}
-                    </div>
-                ),
-                value: 'zhongguo',
-                key: 'zhongguo',
-                children: [
-                    {
-                        label: (
-                            <div style={style}>
-                                <span>test</span>
-                                {button}
-                            </div>
-                        ),
-                        value: 'test',
-                        key: 'test',
-                    },
-                ],
-            },
-            {
-                label: (
-                    <div style={style}>
-                        <span>日本</span>
-                        {button}
-                    </div>
-                ),
-                value: 'riben',
-                key: 'riben',
-            },
+          {
+            label: (
+              <div style={style}>
+                <span>test</span>
+                {button}
+              </div>
+            ),
+            value: 'test',
+            key: 'test',
+          },
         ],
-    },
+      },
+      {
+        label: (
+          <div style={style}>
+            <span>日本</span>
+            {button}
+          </div>
+        ),
+        value: 'riben',
+        key: 'riben',
+      },
+    ],
+  },
 ];
 
-stories.add('tree label using node', () => (
-    <div>
-        <Tree treeData={treeDataWithNode2} blockNode defaultExpandAll/>
-    </div>
-));
+export const TreeLabelUsingNode = () => (
+  <div>
+    <Tree treeData={treeDataWithNode2} blockNode defaultExpandAll />
+  </div>
+);
+
+TreeLabelUsingNode.story = {
+  name: 'tree label using node',
+};
 
 const treeDataTest = [
-    {
-        value: '一级标签1',
-        label: '一级标签1',
-        id: 1,
-        key: '1',
-    },
+  {
+    value: '一级标签1',
+    label: '一级标签1',
+    id: 1,
+    key: '1',
+  },
 ];
 
 class TagSideSheet2 extends React.Component {
-    constructor() {
-        super();
-        this.state = {
-            tagList: [],
-            visibles: false,
-        };
-        this.onVisible = this.onVisible.bind(this);
-        this.renderLabel = this.renderLabel.bind(this);
-        this.transLabel = this.transLabel.bind(this);
-    }
-
-    componentDidMount() {
-        let tagList = [...treeDataTest];
-        this.setState({
-            tagList,
-        });
-    }
-
-    onVisible(visibles) {
-        this.setState({
-            visibles,
-        });
-    }
+  constructor() {
+    super();
+    this.state = {
+      tagList: [],
+      visibles: false,
+    };
+    this.onVisible = this.onVisible.bind(this);
+    this.renderLabel = this.renderLabel.bind(this);
+    this.transLabel = this.transLabel.bind(this);
+  }
+
+  componentDidMount() {
+    let tagList = [...treeDataTest];
+    this.setState({
+      tagList,
+    });
+  }
 
-    renderLabel(item) {
-        const {visibles} = this.state;
-        console.log('rendering label', visibles);
-        return (
-            <Popover trigger="custom" position="bottomLeft" visible={visibles} content={'测试popover'}>
-                <Button
-                    icon={<IconEdit/>}
-                    onClick={e => {
-                        e.stopPropagation();
-                        this.onVisible(!visibles);
-                    }}
-                >
-                    {item.label}
-                </Button>
-            </Popover>
-        );
-    }
+  onVisible(visibles) {
+    this.setState({
+      visibles,
+    });
+  }
 
-    transLabel(list) {
-        // list = cloneDeep(list);
-        list.forEach(item => {
-            item.label = this.renderLabel(item);
-            // item.key += Math.random().toString().slice(0, 5);
-        });
-        return list;
-    }
+  renderLabel(item) {
+    const { visibles } = this.state;
+    console.log('rendering label', visibles);
+    return (
+      <Popover trigger="custom" position="bottomLeft" visible={visibles} content={'测试popover'}>
+        <Button
+          icon={<IconEdit />}
+          onClick={e => {
+            e.stopPropagation();
+            this.onVisible(!visibles);
+          }}
+        >
+          {item.label}
+        </Button>
+      </Popover>
+    );
+  }
 
-    render() {
-        const {tagList = []} = this.state;
-        const transformedTags = this.transLabel(cloneDeep(tagList));
-        console.log('transformedTags', transformedTags, treeDataTest);
-        return <Tree treeData={transformedTags}/>;
-    }
+  transLabel(list) {
+    // list = cloneDeep(list);
+    list.forEach(item => {
+      item.label = this.renderLabel(item);
+      // item.key += Math.random().toString().slice(0, 5);
+    });
+    return list;
+  }
+
+  render() {
+    const { tagList = [] } = this.state;
+    const transformedTags = this.transLabel(cloneDeep(tagList));
+    console.log('transformedTags', transformedTags, treeDataTest);
+    return <Tree treeData={transformedTags} />;
+  }
 }
 
-stories.add('tree label using popover', () => <TagSideSheet2/>);
+export const TreeLabelUsingPopover = () => <TagSideSheet2 />;
 
-stories.add('defaultExpandKeys tree', () => (
-    <>
-        <Tree treeData={treeData1} defaultExpandedKeys={['zhongguo', 'beimeizhou']} blockNode/>
-        <Tree treeData={treeData1} defaultExpandAll blockNode/>
-        <Tree treeData={treeData1} defaultExpandAll multiple blockNode/>
-    </>
-));
+TreeLabelUsingPopover.story = {
+  name: 'tree label using popover',
+};
 
-stories.add('labelInValue tree', () => (
-    <>
-        <Tree treeData={treeData1} labelInValue onChange={e => console.log(e)}/>
-        <Tree treeData={treeData1} labelInValue onChange={e => console.log(e)} multiple/>
-        <Tree treeData={treeDataWithIcon} labelInValue onChange={e => console.log(e)} multiple/>
-    </>
-));
+export const DefaultExpandKeysTree = () => (
+  <>
+    <Tree treeData={treeData1} defaultExpandedKeys={['zhongguo', 'beimeizhou']} blockNode />
+    <Tree treeData={treeData1} defaultExpandAll blockNode />
+    <Tree treeData={treeData1} defaultExpandAll multiple blockNode />
+  </>
+);
 
-class Test extends React.Component {
-    constructor() {
-        super();
-        this.state = {
-            loading: false,
-        };
-    }
+DefaultExpandKeysTree.story = {
+  name: 'defaultExpandKeys tree',
+};
 
-    componentDidMount() {
-        setTimeout(() => {
-            console.log('set loading');
-            this.setState({loading: true});
-        }, 5000);
-    }
+export const LabelInValueTree = () => (
+  <>
+    <Tree treeData={treeData1} labelInValue onChange={e => console.log(e)} />
+    <Tree treeData={treeData1} labelInValue onChange={e => console.log(e)} multiple />
+    <Tree treeData={treeDataWithIcon} labelInValue onChange={e => console.log(e)} multiple />
+  </>
+);
 
-    render() {
-        const treeDataWithNode2 = [
-            {
+LabelInValueTree.story = {
+  name: 'labelInValue tree',
+};
+
+class Test extends React.Component {
+  constructor() {
+    super();
+    this.state = {
+      loading: false,
+    };
+  }
+
+  componentDidMount() {
+    setTimeout(() => {
+      console.log('set loading');
+      this.setState({ loading: true });
+    }, 5000);
+  }
+
+  render() {
+    const treeDataWithNode2 = [
+      {
+        label: (
+          <div style={style}>
+            <span>亚洲</span>
+            <ButtonGroup size="small" theme="borderless">
+              {button}
+            </ButtonGroup>
+          </div>
+        ),
+        value: 'yazhou',
+        key: 'yazhou',
+        children: [
+          {
+            label: (
+              <div style={style}>
+                <span>中国</span>
+                {button}
+              </div>
+            ),
+            value: 'zhongguo',
+            key: 'zhongguo',
+            children: [
+              {
                 label: (
-                    <div style={style}>
-                        <span>亚洲</span>
-                        <ButtonGroup size="small" theme="borderless">
-                            {button}
-                        </ButtonGroup>
-                    </div>
+                  <div style={style}>
+                    <span>test</span>
+                    {button}
+                  </div>
                 ),
-                value: 'yazhou',
-                key: 'yazhou',
-                children: [
-                    {
-                        label: (
-                            <div style={style}>
-                                <span>中国</span>
-                                {button}
-                            </div>
-                        ),
-                        value: 'zhongguo',
-                        key: 'zhongguo',
-                        children: [
-                            {
-                                label: (
-                                    <div style={style}>
-                                        <span>test</span>
-                                        {button}
-                                    </div>
-                                ),
-                                value: 'test',
-                                key: 'test',
-                            },
-                        ],
-                    },
-                    {
-                        label: (
-                            <div style={style}>
-                                <span>日本</span>
-                                {button}
-                            </div>
-                        ),
-                        value: 'riben',
-                        key: 'riben',
-                    },
-                ],
-            },
-        ];
-        return <Tree treeData={treeDataWithNode2}/>;
-    }
+                value: 'test',
+                key: 'test',
+              },
+            ],
+          },
+          {
+            label: (
+              <div style={style}>
+                <span>日本</span>
+                {button}
+              </div>
+            ),
+            value: 'riben',
+            key: 'riben',
+          },
+        ],
+      },
+    ];
+    return <Tree treeData={treeDataWithNode2} />;
+  }
 }
 
-stories.add('setState after 5s', () => <Test/>);
+export const SetStateAfter5S = () => <Test />;
 
-class DemoExpandedKeys extends React.Component {
-    constructor() {
-        super();
-        this.state = {
-            expand: ['zhongguo', 'beimeizhou'],
-        };
-    }
+SetStateAfter5S.story = {
+  name: 'setState after 5s',
+};
 
-    onExpand(expand) {
-        console.log(expand);
-        this.setState({expand});
-    }
+class DemoExpandedKeys extends React.Component {
+  constructor() {
+    super();
+    this.state = {
+      expand: ['zhongguo', 'beimeizhou'],
+    };
+  }
 
-    render() {
-        return (
-            <Tree
-                style={{width: 300}}
-                dropdownStyle={{maxHeight: 400, overflow: 'auto'}}
-                treeData={treeData1}
-                expandedKeys={this.state.expand}
-                placeholder="Please select"
-                onExpand={(e, rest) => this.onExpand(e, rest)}
-            />
-        );
-    }
-}
+  onExpand(expand) {
+    console.log(expand);
+    this.setState({ expand });
+  }
+
+  render() {
+    return (
+      <Tree
+        style={{ width: 300 }}
+        dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
+        treeData={treeData1}
+        expandedKeys={this.state.expand}
+        placeholder="Please select"
+        onExpand={(e, rest) => this.onExpand(e, rest)}
+      />
+    );
+  }
+}
 
 class DemoExpandeKeysMulti extends React.Component {
-    constructor() {
-        super();
-        this.state = {
-            expand: ['zhongguo'],
-        };
-    }
+  constructor() {
+    super();
+    this.state = {
+      expand: ['zhongguo'],
+    };
+  }
 
-    onExpand(expand) {
-        console.log(expand);
-        this.setState({expand});
-    }
+  onExpand(expand) {
+    console.log(expand);
+    this.setState({ expand });
+  }
 
-    render() {
-        return (
-            <Tree
-                style={{width: 300}}
-                multiple
-                dropdownStyle={{maxHeight: 400, overflow: 'auto'}}
-                treeData={treeData1}
-                expandedKeys={this.state.expand}
-                placeholder="Please select"
-                onExpand={e => this.onExpand(e)}
-            />
-        );
-    }
+  render() {
+    return (
+      <Tree
+        style={{ width: 300 }}
+        multiple
+        dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
+        treeData={treeData1}
+        expandedKeys={this.state.expand}
+        placeholder="Please select"
+        onExpand={e => this.onExpand(e)}
+      />
+    );
+  }
 }
 
-stories.add('expandedKeys', () => (
-    <>
-        <DemoExpandedKeys/>
-        <br/>
-        <DemoExpandeKeysMulti/>
-    </>
-));
+export const ExpandedKeys = () => (
+  <>
+    <DemoExpandedKeys />
+    <br />
+    <DemoExpandeKeysMulti />
+  </>
+);
+
+ExpandedKeys.story = {
+  name: 'expandedKeys',
+};
 
 class DmExpandedKeys extends React.Component {
-    constructor() {
-        super();
-        this.state = {
-            treeData: [
-                {
-                    key: '0',
-                    label: 'item-0',
-                    value: '0',
-                },
-            ],
+  constructor() {
+    super();
+    this.state = {
+      treeData: [
+        {
+          key: '0',
+          label: 'item-0',
+          value: '0',
+        },
+      ],
+    };
+    this.add = this.add.bind(this);
+  }
+
+  add() {
+    let itemLength = Math.floor(Math.random() * 5) + 1;
+    let treeData = new Array(itemLength).fill(0).map((v, i) => {
+      let length = Math.floor(Math.random() * 3);
+      let children = new Array(length).fill(0).map((cv, ci) => {
+        let child = {
+          key: `${i}-${ci}`,
+          label: `Leaf-${i}-${ci}`,
+          value: `${i}-${ci}`,
         };
-        this.add = this.add.bind(this);
-    }
-
-    add() {
-        let itemLength = Math.floor(Math.random() * 5) + 1;
-        let treeData = new Array(itemLength).fill(0).map((v, i) => {
-            let length = Math.floor(Math.random() * 3);
-            let children = new Array(length).fill(0).map((cv, ci) => {
-                let child = {
-                    key: `${i}-${ci}`,
-                    label: `Leaf-${i}-${ci}`,
-                    value: `${i}-${ci}`,
-                };
-                return child;
-            });
-            let item = {
-                key: `${i}`,
-                label: `Item-${i}`,
-                value: `${i}`,
-                children,
-            };
-            return item;
-        });
-        this.setState({treeData});
-    }
+        return child;
+      });
+      let item = {
+        key: `${i}`,
+        label: `Item-${i}`,
+        value: `${i}`,
+        children,
+      };
+      return item;
+    });
+    this.setState({ treeData });
+  }
 
-    render() {
-        const {treeData} = this.state;
-        return (
-            <>
-                <Tree treeData={this.state.treeData} expandedKeys={['0', '1']}/>
-                <br/>
-                <Button onClick={this.add}>动态改变数据</Button>
-            </>
-        );
-    }
+  render() {
+    const { treeData } = this.state;
+    return (
+      <>
+        <Tree treeData={this.state.treeData} expandedKeys={['0', '1']} />
+        <br />
+        <Button onClick={this.add}>动态改变数据</Button>
+      </>
+    );
+  }
 }
 
-stories.add('dynamic expandKeys', () => (
-    <>
-        <DmExpandedKeys/>
-    </>
-));
+export const DynamicExpandKeys = () => (
+  <>
+    <DmExpandedKeys />
+  </>
+);
+
+DynamicExpandKeys.story = {
+  name: 'dynamic expandKeys',
+};
 
 class DmSelectedKeys extends React.Component {
-    constructor() {
-        super();
-        this.state = {
-            treeData: [
-                {
-                    key: '0',
-                    label: 'item-0',
-                    value: '0',
-                },
-            ],
+  constructor() {
+    super();
+    this.state = {
+      treeData: [
+        {
+          key: '0',
+          label: 'item-0',
+          value: '0',
+        },
+      ],
+    };
+    this.add = this.add.bind(this);
+  }
+
+  add() {
+    let itemLength = Math.floor(Math.random() * 5) + 1;
+    let treeData = new Array(itemLength).fill(0).map((v, i) => {
+      let length = Math.floor(Math.random() * 3);
+      let children = new Array(length).fill(0).map((cv, ci) => {
+        let child = {
+          key: `${i}-${ci}`,
+          label: `Leaf-${i}-${ci}`,
+          value: `${i}-${ci}`,
         };
-        this.add = this.add.bind(this);
-    }
-
-    add() {
-        let itemLength = Math.floor(Math.random() * 5) + 1;
-        let treeData = new Array(itemLength).fill(0).map((v, i) => {
-            let length = Math.floor(Math.random() * 3);
-            let children = new Array(length).fill(0).map((cv, ci) => {
-                let child = {
-                    key: `${i}-${ci}`,
-                    label: `Leaf-${i}-${ci}`,
-                    value: `${i}-${ci}`,
-                };
-                return child;
-            });
-            let item = {
-                key: `${i}`,
-                label: `Item-${i}`,
-                value: `${i}`,
-                children,
-            };
-            return item;
-        });
-        this.setState({treeData});
-    }
+        return child;
+      });
+      let item = {
+        key: `${i}`,
+        label: `Item-${i}`,
+        value: `${i}`,
+        children,
+      };
+      return item;
+    });
+    this.setState({ treeData });
+  }
 
-    render() {
-        const {treeData} = this.state;
-        return (
-            <>
-                <Tree treeData={treeData} value={['0-0']} onChange={e => console.log(e)}/>
-                <br/>
-                <Button onClick={this.add}>动态改变数据</Button>
-            </>
-        );
-    }
+  render() {
+    const { treeData } = this.state;
+    return (
+      <>
+        <Tree treeData={treeData} value={['0-0']} onChange={e => console.log(e)} />
+        <br />
+        <Button onClick={this.add}>动态改变数据</Button>
+      </>
+    );
+  }
 }
 
-// the demo will not work anymore as value does not exist when the tree mounts
-stories.add('dynamic selectedKey', () => (
-    <>
-        <DmSelectedKeys/>
-    </>
-));
+export const DynamicSelectedKey = () => (
+  <>
+    <DmSelectedKeys />
+  </>
+);
 
-stories.add('large amount of data', () => (
-    <>
-        <BigTree/>
-    </>
-));
+DynamicSelectedKey.story = {
+  name: 'dynamic selectedKey',
+};
 
-stories.add('autosizer', () => (
-    <div style={{
+export const LargeAmountOfData = () => (
+  <>
+    <BigTree />
+  </>
+);
+
+LargeAmountOfData.story = {
+  name: 'large amount of data',
+};
+
+export const Autosizer = () => (
+  <div
+    style={{
+      boxSizing: 'border-box',
+      height: 400,
+      width: 200,
+    }}
+  >
+    <div
+      style={{
         boxSizing: 'border-box',
-        height: 400,
+        height: '50%',
         width: 200,
-    }}>
-        <div
+      }}
+    >
+      <AutoSizer
+      // defaultHeight={defaultHeight}
+      // defaultWidth={defaultWidth}
+      >
+        {({ height, width }) => (
+          <div
             style={{
-                boxSizing: 'border-box',
-                height: '50%',
-                width: 200,
+              width: width,
+              height: height,
             }}
-        >
-            <AutoSizer
-                // defaultHeight={defaultHeight}
-                // defaultWidth={defaultWidth}
-            >
-                {({height, width}) => (
-                    <div
-                        style={{
-                            width: width,
-                            height: height,
-                        }}
-                    >
-                        {`width:${width}, height:${height}`}
-                    </div>
-                )}
-            </AutoSizer>
-        </div>
+          >
+            {`width:${width}, height:${height}`}
+          </div>
+        )}
+      </AutoSizer>
     </div>
-));
+  </div>
+);
+
+Autosizer.story = {
+  name: 'autosizer',
+};
 
 const MotionCustomLabelDemo = () => {
-    const treeData = [
-        {
-            label: '亚洲',
-            value: 'Asia',
-            key: '0',
-            children: [
-                {
-                    label: '中国',
-                    value: 'China',
-                    key: '0-0',
-                    children: [
-                        {
-                            label: '北京',
-                            value: 'Beijing',
-                            key: '0-0-0',
-                        },
-                        {
-                            label: '上海',
-                            value: 'Shanghai',
-                            key: '0-0-1',
-                        },
-                    ],
-                },
-            ],
-        },
+  const treeData = [
+    {
+      label: '亚洲',
+      value: 'Asia',
+      key: '0',
+      children: [
         {
-            label: '北美洲',
-            value: 'North America',
-            key: '1',
+          label: '中国',
+          value: 'China',
+          key: '0-0',
+          children: [
+            {
+              label: '北京',
+              value: 'Beijing',
+              key: '0-0-0',
+            },
+            {
+              label: '上海',
+              value: 'Shanghai',
+              key: '0-0-1',
+            },
+          ],
         },
-    ];
-
-    const [hoverKey, setHoverKey] = useState();
-    const cusLabel = (list = []) => {
-        const recusive = (list = []) => {
-            if (!list.length) {
-                return;
-            }
-            list.forEach(item => {
-                const {type, label, key} = item;
-                item.label = (
-                    <div onMouseEnter={() => setHoverKey(key)}>
-                        {label}
-                        {hoverKey === key ? <IconMore/> : null}
-                    </div>
-                );
-                recusive(item.children);
-            });
-        };
-        recusive(list);
-        return list;
+      ],
+    },
+    {
+      label: '北美洲',
+      value: 'North America',
+      key: '1',
+    },
+  ];
+
+  const [hoverKey, setHoverKey] = useState();
+  const cusLabel = (list = []) => {
+    const recusive = (list = []) => {
+      if (!list.length) {
+        return;
+      }
+      list.forEach(item => {
+        const { type, label, key } = item;
+        item.label = (
+          <div onMouseEnter={() => setHoverKey(key)}>
+            {label}
+            {hoverKey === key ? <IconMore /> : null}
+          </div>
+        );
+        recusive(item.children);
+      });
     };
-    return <Tree treeData={cusLabel(treeData)} defaultExpandAll/>;
+    recusive(list);
+    return list;
+  };
+  return <Tree treeData={cusLabel(treeData)} defaultExpandAll />;
 };
 
-stories.add('motion custom label', () => <MotionCustomLabelDemo/>);
+export const MotionCustomLabel = () => <MotionCustomLabelDemo />;
+
+MotionCustomLabel.story = {
+  name: 'motion custom label',
+};
 
 const AutoParentDemo = () => {
-    const [expandedKeys, setExpandedKeys] = useState(['beimeizhou']);
-    const [selectedKeys, setSelectedKeys] = useState(['beimeizhou']);
-    const [autoExpandParent, setAutoExpandParent] = useState(true);
-
-    const onExpand = expandedKeys => {
-        console.log('onExpand', expandedKeys);
-        // if not set autoExpandParent to false, if children expanded, parent can not collapse.
-        // or, you can remove all expanded children keys.
-        setExpandedKeys(expandedKeys);
-        setAutoExpandParent(false);
-    };
+  const [expandedKeys, setExpandedKeys] = useState(['beimeizhou']);
+  const [selectedKeys, setSelectedKeys] = useState(['beimeizhou']);
+  const [autoExpandParent, setAutoExpandParent] = useState(true);
+
+  const onExpand = expandedKeys => {
+    console.log('onExpand', expandedKeys);
+    // if not set autoExpandParent to false, if children expanded, parent can not collapse.
+    // or, you can remove all expanded children keys.
+    setExpandedKeys(expandedKeys);
+    setAutoExpandParent(false);
+  };
+
+  const onSelect = (selectedKeys, info) => {
+    console.log('onSelect:', info);
+    setSelectedKeys(selectedKeys);
+  };
+
+  return (
+    <div>
+      <Button
+        onClick={() => {
+          setSelectedKeys(['riben']);
+          setExpandedKeys(['riben']);
+          setAutoExpandParent(true);
+        }}
+      >
+        Update
+      </Button>
+      <Tree
+        onExpand={onExpand}
+        expandedKeys={expandedKeys}
+        autoExpandParent={autoExpandParent}
+        onChange={onSelect}
+        value={selectedKeys}
+        treeData={treeData1}
+        multiple
+      />
+    </div>
+  );
+};
 
-    const onSelect = (selectedKeys, info) => {
-        console.log('onSelect:', info);
-        setSelectedKeys(selectedKeys);
-    };
+export const AutoExpandParent = () => (
+  <>
+    <AutoParentDemo />
+  </>
+);
 
-    return (
-        <div>
-            <Button
-                onClick={() => {
-                    setSelectedKeys(['riben']);
-                    setExpandedKeys(['riben']);
-                    setAutoExpandParent(true);
-                }}
-            >
-                Update
-            </Button>
-            <Tree
-                onExpand={onExpand}
-                expandedKeys={expandedKeys}
-                autoExpandParent={autoExpandParent}
-                onChange={onSelect}
-                value={selectedKeys}
-                treeData={treeData1}
-                multiple
-            />
-        </div>
-    );
+AutoExpandParent.story = {
+  name: 'autoExpandParent',
 };
 
-stories.add('autoExpandParent', () => (
-    <>
-        <AutoParentDemo/>
-    </>
-));
-
 const findDescendantKeys = node => {
-    let res = [node.key];
-    const findChild = item => {
-        if (!item) return;
-        const {children} = item;
-
-        if (children && children.length) {
-            children.forEach(child => {
-                res.push(child.key);
-                findChild(child);
-            });
-        }
-    };
-    findChild(node);
-    return res;
+  let res = [node.key];
+  const findChild = item => {
+    if (!item) return;
+    const { children } = item;
+
+    if (children && children.length) {
+      children.forEach(child => {
+        res.push(child.key);
+        findChild(child);
+      });
+    }
+  };
+  findChild(node);
+  return res;
 };
 
 class DyTreeWithExpandControlled extends React.Component {
-    constructor() {
-        super();
-        this.state = {
-            treeData: [
-                {
-                    key: '0',
-                    label: 'item-0',
-                    value: '0',
-                },
-            ],
-            expandedKeys: [],
-            autoExpandParent: false,
-            inputValue: '',
-            collapsedKeys: new Set([]),
-        };
-    }
-
-    componentDidUpdate(prevProps, prevState) {
-        if (
-            !isEqual(prevState.treeData, this.state.treeData) ||
-            !isEqual(prevState.inputValue, this.state.inputValue)
-        ) {
-            const {treeData, inputValue, collapsedKeys} = this.state;
-            let filteredKeys = [];
-
-            const findFilteredKey = arr => {
-                arr.forEach(item => {
-                    if (item.label.indexOf(inputValue) > -1) {
-                        filteredKeys.push(item.key);
-                    }
-                    if (item.children) {
-                        findFilteredKey(item.children);
-                    }
-                });
-            };
-            findFilteredKey(treeData);
-            const expanded = difference(filteredKeys, [...collapsedKeys]);
-            this.setState({
-                expandedKeys: expanded,
-                autoExpandParent: true,
-            });
-        }
-    }
-
-    add = () => {
-        let itemLength = Math.floor(Math.random() * 5) + 1;
-        let treeData = new Array(itemLength).fill(0).map((v, i) => {
-            let length = Math.floor(Math.random() * 3) + 1;
-            let children = new Array(length).fill(0).map((cv, ci) => {
-                let child = {
-                    key: `${i}-${ci}`,
-                    label: `Leaf-${i}-${ci}`,
-                    value: `${i}-${ci}`,
-                };
-                return child;
-            });
-            let item = {
-                key: `${i}`,
-                label: `Item-${i}`,
-                value: `${i}`,
-                children,
-            };
-            return item;
-        });
-        this.setState({treeData});
-    };
-
-    search = val => {
-        this.setState({inputValue: val});
+  constructor() {
+    super();
+    this.state = {
+      treeData: [
+        {
+          key: '0',
+          label: 'item-0',
+          value: '0',
+        },
+      ],
+      expandedKeys: [],
+      autoExpandParent: false,
+      inputValue: '',
+      collapsedKeys: new Set([]),
     };
-
-    onExpand = (keys, {expanded, node}) => {
-        let collapsed = this.state.collapsedKeys;
-        let desKeys = findDescendantKeys(node);
-        if (!expanded) {
-            desKeys.forEach(key => collapsed.add(key));
-        } else {
-            desKeys.forEach(key => collapsed.has(key) && collapsed.delete(key));
-        }
-        this.setState({
-            expandedKeys: keys,
-            autoExpandParent: false,
-            collapsedKeys: collapsed,
+  }
+
+  componentDidUpdate(prevProps, prevState) {
+    if (
+      !isEqual(prevState.treeData, this.state.treeData) ||
+      !isEqual(prevState.inputValue, this.state.inputValue)
+    ) {
+      const { treeData, inputValue, collapsedKeys } = this.state;
+      let filteredKeys = [];
+
+      const findFilteredKey = arr => {
+        arr.forEach(item => {
+          if (item.label.indexOf(inputValue) > -1) {
+            filteredKeys.push(item.key);
+          }
+          if (item.children) {
+            findFilteredKey(item.children);
+          }
         });
-    };
-
-    render() {
-        const {treeData, expandedKeys, autoExpandParent} = this.state;
-        return (
-            <div>
-                <Tree
-                    treeData={treeData}
-                    filterTreeNode
-                    autoExpandParent={autoExpandParent}
-                    expandedKeys={expandedKeys}
-                    onSearch={this.search}
-                    onExpand={this.onExpand}
-                />
-                <br/>
-                <Button onClick={this.add} style={{margin: 20}}>
-                    动态改变数据
-                </Button>
-            </div>
-        );
+      };
+      findFilteredKey(treeData);
+      const expanded = difference(filteredKeys, [...collapsedKeys]);
+      this.setState({
+        expandedKeys: expanded,
+        autoExpandParent: true,
+      });
     }
+  }
+
+  add = () => {
+    let itemLength = Math.floor(Math.random() * 5) + 1;
+    let treeData = new Array(itemLength).fill(0).map((v, i) => {
+      let length = Math.floor(Math.random() * 3) + 1;
+      let children = new Array(length).fill(0).map((cv, ci) => {
+        let child = {
+          key: `${i}-${ci}`,
+          label: `Leaf-${i}-${ci}`,
+          value: `${i}-${ci}`,
+        };
+        return child;
+      });
+      let item = {
+        key: `${i}`,
+        label: `Item-${i}`,
+        value: `${i}`,
+        children,
+      };
+      return item;
+    });
+    this.setState({ treeData });
+  };
+
+  search = val => {
+    this.setState({ inputValue: val });
+  };
+
+  onExpand = (keys, { expanded, node }) => {
+    let collapsed = this.state.collapsedKeys;
+    let desKeys = findDescendantKeys(node);
+    if (!expanded) {
+      desKeys.forEach(key => collapsed.add(key));
+    } else {
+      desKeys.forEach(key => collapsed.has(key) && collapsed.delete(key));
+    }
+    this.setState({
+      expandedKeys: keys,
+      autoExpandParent: false,
+      collapsedKeys: collapsed,
+    });
+  };
+
+  render() {
+    const { treeData, expandedKeys, autoExpandParent } = this.state;
+    return (
+      <div>
+        <Tree
+          treeData={treeData}
+          filterTreeNode
+          autoExpandParent={autoExpandParent}
+          expandedKeys={expandedKeys}
+          onSearch={this.search}
+          onExpand={this.onExpand}
+        />
+        <br />
+        <Button onClick={this.add} style={{ margin: 20 }}>
+          动态改变数据
+        </Button>
+      </div>
+    );
+  }
 }
 
-stories.add('dynamic treeData with searchValue and controlled expand', () => <DyTreeWithExpandControlled/>);
+export const DynamicTreeDataWithSearchValueAndControlledExpand = () => (
+  <DyTreeWithExpandControlled />
+);
+
+DynamicTreeDataWithSearchValueAndControlledExpand.story = {
+  name: 'dynamic treeData with searchValue and controlled expand',
+};
 
 const CusSearchRender = () => {
-    const [inputValue, setInputValue] = useState('');
-    const ref = useRef();
+  const [inputValue, setInputValue] = useState('');
+  const ref = useRef();
 
-    const setValue = value => {
-        setInputValue(value);
-        ref.current.search(value);
-    };
+  const setValue = value => {
+    setInputValue(value);
+    ref.current.search(value);
+  };
 
-    return (
-        <Tree
-            ref={ref}
-            treeData={treeData1}
-            filterTreeNode
-            showFilteredOnly
-            searchRender={({prefix, placeholder}) => (
-                <Input
-                    prefix={prefix}
-                    placeholder={placeholder}
-                    value={inputValue}
-                    onChange={value => setValue(value)}
-                />
-            )}
+  return (
+    <Tree
+      ref={ref}
+      treeData={treeData1}
+      filterTreeNode
+      showFilteredOnly
+      searchRender={({ prefix, placeholder }) => (
+        <Input
+          prefix={prefix}
+          placeholder={placeholder}
+          value={inputValue}
+          onChange={value => setValue(value)}
         />
-    );
+      )}
+    />
+  );
 };
 
-stories.add('CusSearchRender', () => (
-    <>
-        <CusSearchRender/>
-    </>
-));
+export const _CusSearchRender = () => (
+  <>
+    <CusSearchRender />
+  </>
+);
+
+_CusSearchRender.story = {
+  name: 'CusSearchRender',
+};
 
 const RefSearch = () => {
-    const ref = useRef();
-    const treeData = [
+  const ref = useRef();
+  const treeData = [
+    {
+      label: 'Asia',
+      value: 'Asia',
+      key: '0',
+      children: [
         {
-            label: 'Asia',
-            value: 'Asia',
-            key: '0',
-            children: [
-                {
-                    label: 'China',
-                    value: 'China',
-                    key: '0-0',
-                    children: [
-                        {
-                            label: 'Beijing',
-                            value: 'Beijing',
-                            key: '0-0-0',
-                        },
-                        {
-                            label: 'Shanghai',
-                            value: 'Shanghai',
-                            key: '0-0-1',
-                        },
-                    ],
-                },
-                {
-                    label: 'Japan',
-                    value: 'Japan',
-                    key: '0-1',
-                    children: [
-                        {
-                            label: 'Osaka',
-                            value: 'Osaka',
-                            key: '0-1-0',
-                        },
-                    ],
-                },
-            ],
+          label: 'China',
+          value: 'China',
+          key: '0-0',
+          children: [
+            {
+              label: 'Beijing',
+              value: 'Beijing',
+              key: '0-0-0',
+            },
+            {
+              label: 'Shanghai',
+              value: 'Shanghai',
+              key: '0-0-1',
+            },
+          ],
         },
         {
-            label: 'North America',
-            value: 'North America',
-            key: '1',
-            children: [
-                {
-                    label: 'United States',
-                    value: 'United States',
-                    key: '1-0',
-                },
-                {
-                    label: 'Canada',
-                    value: 'Canada',
-                    key: '1-1',
-                },
-            ],
+          label: 'Japan',
+          value: 'Japan',
+          key: '0-1',
+          children: [
+            {
+              label: 'Osaka',
+              value: 'Osaka',
+              key: '0-1-0',
+            },
+          ],
         },
-    ];
-    return (
-        <div>
-            <Input onChange={v => ref.current.search(v)}/>
-            <Tree
-                treeData={treeData}
-                defaultValue="Shanghai"
-                blockNode={false}
-                ref={ref}
-                filterTreeNode
-                searchRender={() => null}
-            />
-        </div>
-    );
+      ],
+    },
+    {
+      label: 'North America',
+      value: 'North America',
+      key: '1',
+      children: [
+        {
+          label: 'United States',
+          value: 'United States',
+          key: '1-0',
+        },
+        {
+          label: 'Canada',
+          value: 'Canada',
+          key: '1-1',
+        },
+      ],
+    },
+  ];
+  return (
+    <div>
+      <Input onChange={v => ref.current.search(v)} />
+      <Tree
+        treeData={treeData}
+        defaultValue="Shanghai"
+        blockNode={false}
+        ref={ref}
+        filterTreeNode
+        searchRender={() => null}
+      />
+    </div>
+  );
 };
 
-stories.add('RefSearch', () => (
-    <>
-        <RefSearch/>
-    </>
-));
+export const _RefSearch = () => (
+  <>
+    <RefSearch />
+  </>
+);
+
+_RefSearch.story = {
+  name: 'RefSearch',
+};
 
 const initTreeDate = [
-    {
-        label: 'Expand to load',
-        key: '0',
-    },
-    {
-        label: 'Expand to load',
-        key: '1',
-    },
-    {
-        label: 'Tree Node',
-        key: '2',
-        isLeaf: true,
-    },
+  {
+    label: 'Expand to load',
+    key: '0',
+  },
+  {
+    label: 'Expand to load',
+    key: '1',
+  },
+  {
+    label: 'Tree Node',
+    key: '2',
+    isLeaf: true,
+  },
 ];
 
 function updateTreeData(list, key, children) {
-    return list.map(node => {
-        if (node.key === key) {
-            return {...node, children};
-        }
-        if (node.children) {
-            return {...node, children: updateTreeData(node.children, key, children)};
-        }
-
-        return node;
-    });
+  return list.map(node => {
+    if (node.key === key) {
+      return { ...node, children };
+    }
+    if (node.children) {
+      return { ...node, children: updateTreeData(node.children, key, children) };
+    }
+
+    return node;
+  });
 }
 
 const LoadingTreeDemo = () => {
-    const [treeData, setTreeData] = useState(initTreeDate);
-
-    function onLoadData({key, children}) {
-        return new Promise(resolve => {
-            if (children) {
-                resolve();
-                return;
-            }
-
-            setTimeout(() => {
-                setTreeData(origin =>
-                    updateTreeData(origin, key, [
-                        {
-                            label: 'Child Node',
-                            key: `${key}-0`,
-                        },
-                        {
-                            label: 'Child Node',
-                            key: `${key}-1`,
-                        },
-                    ])
-                );
-                resolve();
-            }, 1000);
-        });
-    }
+  const [treeData, setTreeData] = useState(initTreeDate);
+
+  function onLoadData({ key, children }) {
+    return new Promise(resolve => {
+      if (children) {
+        resolve();
+        return;
+      }
+
+      setTimeout(() => {
+        setTreeData(origin =>
+          updateTreeData(origin, key, [
+            {
+              label: 'Child Node',
+              key: `${key}-0`,
+            },
+            {
+              label: 'Child Node',
+              key: `${key}-1`,
+            },
+          ])
+        );
+        resolve();
+      }, 1000);
+    });
+  }
 
-    return <Tree loadData={onLoadData} treeData={cloneDeep(treeData)}/>;
+  return <Tree loadData={onLoadData} treeData={cloneDeep(treeData)} />;
 };
 
-stories.add('loading', () => (
-    <>
-        <LoadingTreeDemo/>
-    </>
-));
+export const Loading = () => (
+  <>
+    <LoadingTreeDemo />
+  </>
+);
+
+Loading.story = {
+  name: 'loading',
+};
 
 const LoadingWithSearch = () => {
-    const [treeData, setTreeData] = useState(initTreeDate);
-
-    function onLoadData({key, children}) {
-        return new Promise(resolve => {
-            if (children) {
-                resolve();
-                return;
-            }
-
-            setTimeout(() => {
-                setTreeData(origin =>
-                    updateTreeData(origin, key, [
-                        {
-                            label: 'Child Node',
-                            key: `${key}-0`,
-                        },
-                        {
-                            label: 'Child Node',
-                            key: `${key}-1`,
-                        },
-                    ])
-                );
-                resolve();
-            }, 1000);
-        });
-    }
+  const [treeData, setTreeData] = useState(initTreeDate);
+
+  function onLoadData({ key, children }) {
+    return new Promise(resolve => {
+      if (children) {
+        resolve();
+        return;
+      }
+
+      setTimeout(() => {
+        setTreeData(origin =>
+          updateTreeData(origin, key, [
+            {
+              label: 'Child Node',
+              key: `${key}-0`,
+            },
+            {
+              label: 'Child Node',
+              key: `${key}-1`,
+            },
+          ])
+        );
+        resolve();
+      }, 1000);
+    });
+  }
+
+  return <Tree loadData={onLoadData} treeData={cloneDeep(treeData)} filterTreeNode />;
+};
+
+export const _LoadingWithSearch = () => (
+  <>
+    <LoadingWithSearch />
+  </>
+);
 
-    return <Tree loadData={onLoadData} treeData={cloneDeep(treeData)} filterTreeNode/>;
+_LoadingWithSearch.story = {
+  name: 'Loading with search',
 };
 
-stories.add('Loading with search', () => (
+const DisabledStrictly = () => {
+  return (
     <>
-        <LoadingWithSearch/>
+      <span> disable shanghai(checked), China </span>
+      <Tree
+        treeData={[
+          {
+            label: 'Asia',
+            value: 'Asia',
+            key: '0',
+            children: [
+              {
+                label: 'China',
+                value: 'China',
+                key: '0-0',
+                disabled: true,
+                children: [
+                  {
+                    label: 'Beijing',
+                    value: 'Beijing',
+                    key: '0-0-0',
+                  },
+                  {
+                    label: 'Shanghai',
+                    value: 'Shanghai',
+                    key: '0-0-1',
+                    disabled: true,
+                  },
+                ],
+              },
+              {
+                label: 'Japan',
+                value: 'Japan',
+                key: '0-1',
+                children: [
+                  {
+                    label: 'Osaka',
+                    value: 'Osaka',
+                    key: '0-1-0',
+                  },
+                ],
+              },
+            ],
+          },
+        ]}
+        defaultValue="Shanghai"
+        multiple
+        defaultExpandAll
+        disableStrictly
+      />
+      <br />
+      <span> disable shanghai(checked), beijing(checked) </span>
+      <Tree
+        treeData={[
+          {
+            label: 'Asia',
+            value: 'Asia',
+            key: '0',
+            children: [
+              {
+                label: 'China',
+                value: 'China',
+                key: '0-0',
+                children: [
+                  {
+                    label: 'Beijing',
+                    value: 'Beijing',
+                    key: '0-0-0',
+                    disabled: true,
+                  },
+                  {
+                    label: 'Shanghai',
+                    value: 'Shanghai',
+                    key: '0-0-1',
+                    disabled: true,
+                  },
+                ],
+              },
+              {
+                label: 'Japan',
+                value: 'Japan',
+                key: '0-1',
+                children: [
+                  {
+                    label: 'Osaka',
+                    value: 'Osaka',
+                    key: '0-1-0',
+                  },
+                ],
+              },
+            ],
+          },
+        ]}
+        defaultValue={['Shanghai', 'Beijing']}
+        multiple
+        defaultExpandAll
+        disableStrictly
+      />
+      <span> disable shanghai(checked) </span>
+      <Tree
+        treeData={[
+          {
+            label: 'Asia',
+            value: 'Asia',
+            key: '0',
+            children: [
+              {
+                label: 'China',
+                value: 'China',
+                key: '0-0',
+                children: [
+                  {
+                    label: 'Beijing',
+                    value: 'Beijing',
+                    key: '0-0-0',
+                  },
+                  {
+                    label: 'Shanghai',
+                    value: 'Shanghai',
+                    key: '0-0-1',
+                    disabled: true,
+                  },
+                ],
+              },
+              {
+                label: 'Japan',
+                value: 'Japan',
+                key: '0-1',
+                children: [
+                  {
+                    label: 'Osaka',
+                    value: 'Osaka',
+                    key: '0-1-0',
+                  },
+                ],
+              },
+            ],
+          },
+        ]}
+        defaultValue={['Shanghai']}
+        multiple
+        defaultExpandAll
+        disableStrictly
+      />
+      <br />
+      <span> disable shanghai </span>
+      <Tree
+        treeData={[
+          {
+            label: 'Asia',
+            value: 'Asia',
+            key: '0',
+            children: [
+              {
+                label: 'China',
+                value: 'China',
+                key: '0-0',
+                children: [
+                  {
+                    label: 'Beijing',
+                    value: 'Beijing',
+                    key: '0-0-0',
+                  },
+                  {
+                    label: 'Chengdu',
+                    value: 'Chengdu',
+                    key: '0-0-2',
+                  },
+                  {
+                    label: 'Shanghai',
+                    value: 'Shanghai',
+                    key: '0-0-1',
+                    disabled: true,
+                  },
+                ],
+              },
+              {
+                label: 'Japan',
+                value: 'Japan',
+                key: '0-1',
+                children: [
+                  {
+                    label: 'Osaka',
+                    value: 'Osaka',
+                    key: '0-1-0',
+                  },
+                ],
+              },
+            ],
+          },
+        ]}
+        multiple
+        defaultExpandAll
+        disableStrictly
+      />
+      <span> disable China(checked) - Shanghai </span>
+      <Tree
+        treeData={[
+          {
+            label: 'Asia',
+            value: 'Asia',
+            key: '0',
+            children: [
+              {
+                label: 'China',
+                value: 'China',
+                key: '0-0',
+                disabled: true,
+                children: [
+                  {
+                    label: 'Beijing',
+                    value: 'Beijing',
+                    key: '0-0-0',
+                  },
+                  {
+                    label: 'Shanghai',
+                    value: 'Shanghai',
+                    key: '0-0-1',
+                    disabled: true,
+                  },
+                ],
+              },
+              {
+                label: 'Japan',
+                value: 'Japan',
+                key: '0-1',
+                children: [
+                  {
+                    label: 'Osaka',
+                    value: 'Osaka',
+                    key: '0-1-0',
+                  },
+                ],
+              },
+            ],
+          },
+        ]}
+        defaultValue="China"
+        multiple
+        defaultExpandAll
+        disableStrictly
+      />
+      <span> disable China </span>
+      <Tree
+        treeData={[
+          {
+            label: 'Asia',
+            value: 'Asia',
+            key: '0',
+            children: [
+              {
+                label: 'China',
+                value: 'China',
+                key: '0-0',
+                disabled: true,
+                children: [
+                  {
+                    label: 'Beijing',
+                    value: 'Beijing',
+                    key: '0-0-0',
+                  },
+                  {
+                    label: 'Shanghai',
+                    value: 'Shanghai',
+                    key: '0-0-1',
+                  },
+                ],
+              },
+              {
+                label: 'Japan',
+                value: 'Japan',
+                key: '0-1',
+                children: [
+                  {
+                    label: 'Osaka',
+                    value: 'Osaka',
+                    key: '0-1-0',
+                  },
+                ],
+              },
+            ],
+          },
+        ]}
+        multiple
+        defaultExpandAll
+        disableStrictly
+      />
     </>
-));
+  );
+};
 
-const DisabledStrictly = () => {
-    return (
-        <>
-            <span> disable shanghai(checked), China </span>
-            <Tree
-                treeData={[
-                    {
-                        label: 'Asia',
-                        value: 'Asia',
-                        key: '0',
-                        children: [
-                            {
-                                label: 'China',
-                                value: 'China',
-                                key: '0-0',
-                                disabled: true,
-                                children: [
-                                    {
-                                        label: 'Beijing',
-                                        value: 'Beijing',
-                                        key: '0-0-0',
-                                    },
-                                    {
-                                        label: 'Shanghai',
-                                        value: 'Shanghai',
-                                        key: '0-0-1',
-                                        disabled: true,
-                                    },
-                                ],
-                            },
-                            {
-                                label: 'Japan',
-                                value: 'Japan',
-                                key: '0-1',
-                                children: [
-                                    {
-                                        label: 'Osaka',
-                                        value: 'Osaka',
-                                        key: '0-1-0'
-                                    }
-                                ]
-                            },
-                        ],
-                    }
-                ]}
-                defaultValue='Shanghai'
-                multiple
-                defaultExpandAll
-                disableStrictly
-            />
-            <br/>
-            <span> disable shanghai(checked), beijing(checked) </span>
-            <Tree
-                treeData={[
-                    {
-                        label: 'Asia',
-                        value: 'Asia',
-                        key: '0',
-                        children: [
-                            {
-                                label: 'China',
-                                value: 'China',
-                                key: '0-0',
-                                children: [
-                                    {
-                                        label: 'Beijing',
-                                        value: 'Beijing',
-                                        key: '0-0-0',
-                                        disabled: true,
-                                    },
-                                    {
-                                        label: 'Shanghai',
-                                        value: 'Shanghai',
-                                        key: '0-0-1',
-                                        disabled: true,
-                                    },
-                                ],
-                            },
-                            {
-                                label: 'Japan',
-                                value: 'Japan',
-                                key: '0-1',
-                                children: [
-                                    {
-                                        label: 'Osaka',
-                                        value: 'Osaka',
-                                        key: '0-1-0'
-                                    }
-                                ]
-                            },
-                        ],
-                    }
-                ]}
-                defaultValue={['Shanghai', 'Beijing']}
-                multiple
-                defaultExpandAll
-                disableStrictly
-            />
-            <span> disable shanghai(checked) </span>
-            <Tree
-                treeData={[
-                    {
-                        label: 'Asia',
-                        value: 'Asia',
-                        key: '0',
-                        children: [
-                            {
-                                label: 'China',
-                                value: 'China',
-                                key: '0-0',
-                                children: [
-                                    {
-                                        label: 'Beijing',
-                                        value: 'Beijing',
-                                        key: '0-0-0',
-                                    },
-                                    {
-                                        label: 'Shanghai',
-                                        value: 'Shanghai',
-                                        key: '0-0-1',
-                                        disabled: true,
-                                    },
-                                ],
-                            },
-                            {
-                                label: 'Japan',
-                                value: 'Japan',
-                                key: '0-1',
-                                children: [
-                                    {
-                                        label: 'Osaka',
-                                        value: 'Osaka',
-                                        key: '0-1-0'
-                                    }
-                                ]
-                            },
-                        ],
-                    }
-                ]}
-                defaultValue={['Shanghai']}
-                multiple
-                defaultExpandAll
-                disableStrictly
-            />
-            <br/>
-            <span> disable shanghai </span>
-            <Tree
-                treeData={[
-                    {
-                        label: 'Asia',
-                        value: 'Asia',
-                        key: '0',
-                        children: [
-                            {
-                                label: 'China',
-                                value: 'China',
-                                key: '0-0',
-                                children: [
-                                    {
-                                        label: 'Beijing',
-                                        value: 'Beijing',
-                                        key: '0-0-0',
-                                    },
-                                    {
-                                        label: 'Chengdu',
-                                        value: 'Chengdu',
-                                        key: '0-0-2',
-                                    },
-                                    {
-                                        label: 'Shanghai',
-                                        value: 'Shanghai',
-                                        key: '0-0-1',
-                                        disabled: true,
-                                    },
-                                ],
-                            },
-                            {
-                                label: 'Japan',
-                                value: 'Japan',
-                                key: '0-1',
-                                children: [
-                                    {
-                                        label: 'Osaka',
-                                        value: 'Osaka',
-                                        key: '0-1-0'
-                                    }
-                                ]
-                            },
-                        ],
-                    }
-                ]}
-                multiple
-                defaultExpandAll
-                disableStrictly
-            />
-            <span> disable China(checked) - Shanghai </span>
-            <Tree
-                treeData={[
-                    {
-                        label: 'Asia',
-                        value: 'Asia',
-                        key: '0',
-                        children: [
-                            {
-                                label: 'China',
-                                value: 'China',
-                                key: '0-0',
-                                disabled: true,
-                                children: [
-                                    {
-                                        label: 'Beijing',
-                                        value: 'Beijing',
-                                        key: '0-0-0',
-                                    },
-                                    {
-                                        label: 'Shanghai',
-                                        value: 'Shanghai',
-                                        key: '0-0-1',
-                                        disabled: true,
-                                    },
-                                ],
-                            },
-                            {
-                                label: 'Japan',
-                                value: 'Japan',
-                                key: '0-1',
-                                children: [
-                                    {
-                                        label: 'Osaka',
-                                        value: 'Osaka',
-                                        key: '0-1-0'
-                                    }
-                                ]
-                            },
-                        ],
-                    }
-                ]}
-                defaultValue='China'
-                multiple
-                defaultExpandAll
-                disableStrictly
-            />
-            <span> disable China </span>
-            <Tree
-                treeData={[
-                    {
-                        label: 'Asia',
-                        value: 'Asia',
-                        key: '0',
-                        children: [
-                            {
-                                label: 'China',
-                                value: 'China',
-                                key: '0-0',
-                                disabled: true,
-                                children: [
-                                    {
-                                        label: 'Beijing',
-                                        value: 'Beijing',
-                                        key: '0-0-0',
-                                    },
-                                    {
-                                        label: 'Shanghai',
-                                        value: 'Shanghai',
-                                        key: '0-0-1',
-                                    },
-                                ],
-                            },
-                            {
-                                label: 'Japan',
-                                value: 'Japan',
-                                key: '0-1',
-                                children: [
-                                    {
-                                        label: 'Osaka',
-                                        value: 'Osaka',
-                                        key: '0-1-0'
-                                    }
-                                ]
-                            },
-                        ],
-                    }
-                ]}
-                multiple
-                defaultExpandAll
-                disableStrictly
-            />
-        </>
-    )
-}
+export const DisableStrictly = () => <DisabledStrictly />;
 
-stories.add('disableStrictly', () => <DisabledStrictly/>);
+DisableStrictly.story = {
+  name: 'disableStrictly',
+};
 
 const ActionTree = () => {
-    let initData = [{
-        label: 'Asia',
-        value: 'Asia',
-        key: 'asia',
-        children: [{
-            label: 0,
-            value: `${0}`,
-            key: `${0}`,
-        }, {
-            label: 1,
-            value: `${1}`,
-            key: `${1}`,
-        }, {
-            label: 2,
-            value: `${2}`,
-            key: `${2}`,
-        }, {
-            label: 3,
-            value: `${3}`,
-            key: `${3}`,
-        }, {
-            label: 4,
-            value: `${4}`,
-            key: `${4}`,
-        }]
-    }];
-
-    const [data, setData] = useState(initData);
-
-    const remove = key => {
-        let ind = data[0].children.findIndex(item => item.key === key);
-        if (ind >= 0) {
-            let items = cloneDeep(data);
-            items[0].children.splice(ind, 1);
-            setData(items);
-        }
+  let initData = [
+    {
+      label: 'Asia',
+      value: 'Asia',
+      key: 'asia',
+      children: [
+        {
+          label: 0,
+          value: `${0}`,
+          key: `${0}`,
+        },
+        {
+          label: 1,
+          value: `${1}`,
+          key: `${1}`,
+        },
+        {
+          label: 2,
+          value: `${2}`,
+          key: `${2}`,
+        },
+        {
+          label: 3,
+          value: `${3}`,
+          key: `${3}`,
+        },
+        {
+          label: 4,
+          value: `${4}`,
+          key: `${4}`,
+        },
+      ],
+    },
+  ];
+
+  const [data, setData] = useState(initData);
+
+  const remove = key => {
+    let ind = data[0].children.findIndex(item => item.key === key);
+    if (ind >= 0) {
+      let items = cloneDeep(data);
+      items[0].children.splice(ind, 1);
+      setData(items);
     }
+  };
 
-    return (
-        <Tree
-            treeData={cloneDeep(data)}
-            renderLabel={(label, data) => (<div>{label}<Button onClick={() => remove(data.key)}>remove</Button></div>)}
-        />
-    );
+  return (
+    <Tree
+      treeData={cloneDeep(data)}
+      renderLabel={(label, data) => (
+        <div>
+          {label}
+          <Button onClick={() => remove(data.key)}>remove</Button>
+        </div>
+      )}
+    />
+  );
 };
 
-stories.add('Delete or Add Child Node', () => <ActionTree/>);
+export const DeleteOrAddChildNode = () => <ActionTree />;
 
+DeleteOrAddChildNode.story = {
+  name: 'Delete or Add Child Node',
+};
 
 const MutipleHLTree = () => {
-    const [selected, setSelected] = useState(new Set());
-    const [selectedThroughParent, setSelectedThroughParent] = useState(new Set());
-
-    const findDescendantKeys = (node) => {
-        let res = [node.key];
-        const findChild = item => {
-            if (!item) return;
-            const {children} = item;
-
-            if (children && children.length) {
-                children.forEach(child => {
-                    res.push(child.key);
-                    findChild(child);
-                });
-            }
-        };
-        findChild(node);
-        return res;
-    }
-
-    const handleSelect = (key, bool, node) => {
-        setSelected(new Set([key]));
-        const descendantKeys = findDescendantKeys(node);
-        setSelectedThroughParent(new Set(descendantKeys));
-    }
+  const [selected, setSelected] = useState(new Set());
+  const [selectedThroughParent, setSelectedThroughParent] = useState(new Set());
 
-    const renderLabel = ({
-        className,
-        data,
-        onClick,
-        expandIcon
-    }) => {
-        const {label, icon, key} = data;
-        const isLeaf = !(data.children && data.children.length);
-        const style = {
-            backgroundColor: selected.has(key)
-                ? 'rgba(var(--semi-blue-0), 1)'
-                : selectedThroughParent.has(key)
-                    ? 'rgba(var(--semi-blue-0), .5)' : 'transparent'
-        }
-        return (
-            <li
-                className={className}
-                role="treenode"
-                onClick={onClick}
-                style={style}
-            >
-                {isLeaf ? null : expandIcon}
-                {icon ? icon : null}
-                <span>{label}</span>
-            </li>
-        )
-    }
+  const findDescendantKeys = node => {
+    let res = [node.key];
+    const findChild = item => {
+      if (!item) return;
+      const { children } = item;
 
-    const treeStyle = {
-        width: 260,
-        height: 420,
-        border: '1px solid var(--semi-color-border)'
-    }
+      if (children && children.length) {
+        children.forEach(child => {
+          res.push(child.key);
+          findChild(child);
+        });
+      }
+    };
+    findChild(node);
+    return res;
+  };
+
+  const handleSelect = (key, bool, node) => {
+    setSelected(new Set([key]));
+    const descendantKeys = findDescendantKeys(node);
+    setSelectedThroughParent(new Set(descendantKeys));
+  };
+
+  const renderLabel = ({ className, data, onClick, expandIcon }) => {
+    const { label, icon, key } = data;
+    const isLeaf = !(data.children && data.children.length);
+    const style = {
+      backgroundColor: selected.has(key)
+        ? 'rgba(var(--semi-blue-0), 1)'
+        : selectedThroughParent.has(key)
+        ? 'rgba(var(--semi-blue-0), .5)'
+        : 'transparent',
+    };
     return (
-        <Tree
-            treeData={treeData1}
-            renderFullLabel={renderLabel}
-            onSelect={handleSelect}
-            style={treeStyle}
-        />
-    )
-}
-
-stories.add('renderOuterLable', () => <MutipleHLTree/>)
-
-stories.add('tree without value props', () => (
+      <li className={className} role="treenode" onClick={onClick} style={style}>
+        {isLeaf ? null : expandIcon}
+        {icon ? icon : null}
+        <span>{label}</span>
+      </li>
+    );
+  };
+
+  const treeStyle = {
+    width: 260,
+    height: 420,
+    border: '1px solid var(--semi-color-border)',
+  };
+  return (
     <Tree
-        treeData={treeDataWithoutValue}
-        value="meiguo"
-        defaultExpandAll
-        onChange={(...args) => console.log(args)}
+      treeData={treeData1}
+      renderFullLabel={renderLabel}
+      onSelect={handleSelect}
+      style={treeStyle}
     />
-));
+  );
+};
+
+export const RenderOuterLable = () => <MutipleHLTree />;
+
+RenderOuterLable.story = {
+  name: 'renderOuterLable',
+};
+
+export const TreeWithoutValueProps = () => (
+  <Tree
+    treeData={treeDataWithoutValue}
+    value="meiguo"
+    defaultExpandAll
+    onChange={(...args) => console.log(args)}
+  />
+);
+
+TreeWithoutValueProps.story = {
+  name: 'tree without value props',
+};
 
 const DnDTree = () => {
-    
-    const initialData = [
+  const initialData = [
+    {
+      label: 'Asia',
+      value: 'Asia',
+      key: '0',
+      children: [
         {
-            label: 'Asia',
-            value: 'Asia',
-            key: '0',
-            children: [
-                {
-                    label: 'China',
-                    value: 'China',
-                    key: '0-0',
-                    children: [
-                        {
-                            label: 'Beijing',
-                            value: 'Beijing',
-                            key: '0-0-0',
-                        },
-                        {
-                            label: 'Shanghai',
-                            value: 'Shanghai',
-                            key: '0-0-1',
-                        },
-                    ],
-                },
-                {
-                    label: 'Japan',
-                    value: 'Japan',
-                    key: '0-1',
-                    children: [
-                        {
-                            label: 'Osaka',
-                            value: 'Osaka',
-                            key: '0-1-0'
-                        }
-                    ]
-                },
-            ],
+          label: 'China',
+          value: 'China',
+          key: '0-0',
+          children: [
+            {
+              label: 'Beijing',
+              value: 'Beijing',
+              key: '0-0-0',
+            },
+            {
+              label: 'Shanghai',
+              value: 'Shanghai',
+              key: '0-0-1',
+            },
+          ],
         },
         {
-            label: 'North America',
-            value: 'North America',
-            key: '1',
-            children: [
-                {
-                    label: 'United States',
-                    value: 'United States',
-                    key: '1-0'
-                },
-                {
-                    label: 'Canada',
-                    value: 'Canada',
-                    key: '1-1'
-                }
-            ]
+          label: 'Japan',
+          value: 'Japan',
+          key: '0-1',
+          children: [
+            {
+              label: 'Osaka',
+              value: 'Osaka',
+              key: '0-1-0',
+            },
+          ],
+        },
+      ],
+    },
+    {
+      label: 'North America',
+      value: 'North America',
+      key: '1',
+      children: [
+        {
+          label: 'United States',
+          value: 'United States',
+          key: '1-0',
         },
         {
-            label: 'Europe',
-            value: 'Europe',
-            key: '2',
-        }
-    ];
-
-    const [treeData, setTreeData] = useState(initialData);
-
-    // const [expandedKeys, setExpandedKeys] = useState(['zhongguo']);
+          label: 'Canada',
+          value: 'Canada',
+          key: '1-1',
+        },
+      ],
+    },
+    {
+      label: 'Europe',
+      value: 'Europe',
+      key: '2',
+    },
+  ];
+
+  const [treeData, setTreeData] = useState(initialData);
+
+  // const [expandedKeys, setExpandedKeys] = useState(['zhongguo']);
+
+  function onDragEnter(info) {
+    console.log(info);
+    // if in controlled expandedKeys mode
+    // setExpandedKeys(info.expandedKeys)
+  }
+
+  function onDrop(info) {
+    const { dropToGap, node, dragNode } = info;
+    const dropKey = node.key;
+    const dragKey = dragNode.key;
+    const dropPos = node.pos.split('-');
+    const dropPosition = info.dropPosition - Number(dropPos[dropPos.length - 1]);
+    const data = [...treeData];
+    const loop = (data, key, callback) => {
+      data.forEach((item, ind, arr) => {
+        if (item.key === key) return callback(item, ind, arr);
+        if (item.children) return loop(item.children, key, callback);
+      });
+    };
 
-    function onDragEnter(info) {
-        console.log(info);
-        // if in controlled expandedKeys mode
-        // setExpandedKeys(info.expandedKeys)
-    }
+    let dragObj;
+    loop(data, dragKey, (item, ind, arr) => {
+      arr.splice(ind, 1);
+      dragObj = item;
+    });
 
-    function onDrop(info) {
-        const {dropToGap, node, dragNode} = info;
-        const dropKey = node.key;
-        const dragKey = dragNode.key;
-        const dropPos = node.pos.split('-');
-        const dropPosition = info.dropPosition - Number(dropPos[dropPos.length - 1]);
-        const data = [...treeData];
-        const loop = (data, key, callback) => {
-            data.forEach((item, ind, arr) => {
-                if (item.key === key) return callback(item, ind, arr);
-                if (item.children) return loop(item.children, key, callback);
-            })
-        }
-
-        let dragObj;
-        loop(data, dragKey, (item, ind, arr) => {
-            arr.splice(ind, 1);
-            dragObj = item;
-        })
-
-        if (!dropToGap) {
-            // inset into the dropPosition
-            loop(data, dropKey, (item, ind, arr) => {
-                item.children = item.children || [];
-                item.children.push(dragObj)
-            })
-        } else if (dropPosition === 1 && node.children && node.expanded) {
-            // has children && expanded and drop into the node bottom gap
-            // insert to the top 这里我们添加在头部,可以是任意位置
-            loop(data, dropKey, item => {
-                item.children = item.children || [];
-                item.children.unshift(dragObj)
-            })
-        } else {
-            let dropNodeInd;
-            let dropNodePosArr;
-            loop(data, dropKey, (item, ind, arr) => {
-                dropNodePosArr = arr;
-                dropNodeInd = ind;
-            })
-            if (dropPosition === -1) {
-                // insert to top
-                dropNodePosArr.splice(dropNodeInd, 0, dragObj)
-            } else {
-                // insert to bottom
-                dropNodePosArr.splice(dropNodeInd + 1, 0, dragObj)
-            }
-        }
-        setTreeData(data)
+    if (!dropToGap) {
+      // inset into the dropPosition
+      loop(data, dropKey, (item, ind, arr) => {
+        item.children = item.children || [];
+        item.children.push(dragObj);
+      });
+    } else if (dropPosition === 1 && node.children && node.expanded) {
+      // has children && expanded and drop into the node bottom gap
+      // insert to the top 这里我们添加在头部,可以是任意位置
+      loop(data, dropKey, item => {
+        item.children = item.children || [];
+        item.children.unshift(dragObj);
+      });
+    } else {
+      let dropNodeInd;
+      let dropNodePosArr;
+      loop(data, dropKey, (item, ind, arr) => {
+        dropNodePosArr = arr;
+        dropNodeInd = ind;
+      });
+      if (dropPosition === -1) {
+        // insert to top
+        dropNodePosArr.splice(dropNodeInd, 0, dragObj);
+      } else {
+        // insert to bottom
+        dropNodePosArr.splice(dropNodeInd + 1, 0, dragObj);
+      }
     }
+    setTreeData(data);
+  }
 
-    return <Tree
-        treeData={treeData}
-        draggable
-        //expandedKeys={expandedKeys}
-        onDragEnter={onDragEnter}
-        onDrop={onDrop}
-    />;
+  return (
+    <Tree
+      treeData={treeData}
+      draggable
+      //expandedKeys={expandedKeys}
+      onDragEnter={onDragEnter}
+      onDrop={onDrop}
+    />
+  );
 };
 
-stories.add('draggable Tree', () => <DnDTree/>)
+export const DraggableTree = () => <DnDTree />;
+
+DraggableTree.story = {
+  name: 'draggable Tree',
+};
 
 const TestTree = () => {
-    return (
-        <Tree
-            treeData={testData}
-            // motion={false}
-            style={{height: '100%'}}
-            filterTreeNode
-            expandAction="click"
-            showFilteredOnly
-        />
-    );
+  return (
+    <Tree
+      treeData={testData}
+      // motion={false}
+      style={{ height: '100%' }}
+      filterTreeNode
+      expandAction="click"
+      showFilteredOnly
+    />
+  );
 };
 
-stories.add('draggable', () => <TestTree/>);
+export const Draggable = () => <TestTree />;
+
+Draggable.story = {
+  name: 'draggable',
+};
 
-stories.add('renderFullLabel with draggable', () => {
-        const [selected, setSelected] = useState(new Set());
-        const [selectedThroughParent, setSelectedThroughParent] = useState(new Set());
-        const defaultTreeData = [
+export const RenderFullLabelWithDraggable = () => {
+  const [selected, setSelected] = useState(new Set());
+  const [selectedThroughParent, setSelectedThroughParent] = useState(new Set());
+  const defaultTreeData = [
+    {
+      label: '黑色固定按钮',
+      key: 'fix-btn-0',
+    },
+    {
+      label: '模块',
+      key: 'module-0',
+      children: [
+        {
+          label: '可自由摆放的组件',
+          key: 'free-compo-0',
+        },
+        {
+          label: '分栏容器',
+          key: 'split-col-0',
+          children: [
             {
-                label: '黑色固定按钮',
-                key: 'fix-btn-0'
+              label: '按钮组件',
+              key: 'btn-0',
             },
             {
-                label: '模块',
-                key: 'module-0',
-                children: [
-                    {
-                        label: '可自由摆放的组件',
-                        key: 'free-compo-0',
-                    },
-                    {
-                        label: '分栏容器',
-                        key: 'split-col-0',
-                        children: [
-                            {
-                                label: '按钮组件',
-                                key: 'btn-0'
-                            },
-                            {
-                                label: '按钮组件',
-                                key: 'btn-1'
-                            }
-                        ]
-                    },
-                ],
+              label: '按钮组件',
+              key: 'btn-1',
             },
-            {
-                label: '模块',
-                key: 'module-1',
-                children: [
-                    {
-                        label: '自定义组件',
-                        key: 'cus-0'
-                    }
-                ]
-            }
-        ]
-        const [treeData, setTreeData] = useState(defaultTreeData);
-
-        const onDrop = (info) => {
-            const {dropToGap, node, dragNode} = info;
-            const dropKey = node.key;
-            const dragKey = dragNode.key;
-            const dropPos = node.pos.split('-');
-            const dropPosition = info.dropPosition - Number(dropPos[dropPos.length - 1]);
-
-            const data = [...treeData];
-            const loop = (data, key, callback) => {
-                data.forEach((item, ind, arr) => {
-                    if (item.key === key) return callback(item, ind, arr);
-                    if (item.children) return loop(item.children, key, callback);
-                })
-            }
-
-            let dragObj;
-            loop(data, dragKey, (item, ind, arr) => {
-                arr.splice(ind, 1);
-                dragObj = item;
-            })
-
-            if (!dropToGap) {
-                loop(data, dropKey, (item, ind, arr) => {
-                    item.children = item.children || [];
-                    item.children.push(dragObj)
-                })
-            } else if (dropPosition === 1 && node.children && node.expanded) {
-                loop(data, dropKey, item => {
-                    item.children = item.children || [];
-                    item.children.unshift(dragObj)
-                })
-            } else {
-                let dropNodeInd;
-                let dropNodePosArr;
-                loop(data, dropKey, (item, ind, arr) => {
-                    dropNodePosArr = arr;
-                    dropNodeInd = ind;
-                })
-                if (dropPosition === -1) {
-                    dropNodePosArr.splice(dropNodeInd, 0, dragObj)
-                } else {
-                    dropNodePosArr.splice(dropNodeInd + 1, 0, dragObj)
-                }
-            }
-            setTreeData(data)
-        }
-
-        const findDescendantKeys = (node) => {
-            let res = [node.key];
-            const findChild = item => {
-                if (!item) return;
-                const {children} = item;
-
-                if (children && children.length) {
-                    children.forEach(child => {
-                        res.push(child.key);
-                        findChild(child);
-                    });
-                }
-            };
-            findChild(node);
-            return res;
-        }
-
-        const handleSelect = (key, bool, node) => {
-            setSelected(new Set([key]));
-            const descendantKeys = findDescendantKeys(node);
-            setSelectedThroughParent(new Set(descendantKeys));
-        }
-
-        const renderLabel = ({
-            className,
-            data,
-            onClick,
-            expandIcon
-        }) => {
-            const {label, icon, key} = data;
-            const isLeaf = !(data.children && data.children.length);
-            const style = {
-                backgroundColor: selected.has(key)
-                    ? 'rgba(var(--semi-blue-0), 1)'
-                    : selectedThroughParent.has(key)
-                        ? 'rgba(var(--semi-blue-0), .5)' : 'transparent'
-            }
-            return (
-                <li
-                    className={className}
-                    role="treenode"
-                    onClick={onClick}
-                    style={style}
-                >
-                    {isLeaf ? <span style={{width: 24}}></span> : expandIcon}
-                    {icon ? icon : null}
-                    <span>{label}</span>
-                </li>
-            )
-        }
-
-        const treeStyle = {
-            height: 420,
-            border: '1px solid var(--semi-color-border)'
-        }
-
-
-        return <Tree
-            treeData={treeData}
-            draggable
-            onDrop={onDrop}
-            renderFullLabel={renderLabel}
-            onSelect={handleSelect}
-            style={treeStyle}
-            defaultExpandAll
-        />;
+          ],
+        },
+      ],
+    },
+    {
+      label: '模块',
+      key: 'module-1',
+      children: [
+        {
+          label: '自定义组件',
+          key: 'cus-0',
+        },
+      ],
+    },
+  ];
+  const [treeData, setTreeData] = useState(defaultTreeData);
+
+  const onDrop = info => {
+    const { dropToGap, node, dragNode } = info;
+    const dropKey = node.key;
+    const dragKey = dragNode.key;
+    const dropPos = node.pos.split('-');
+    const dropPosition = info.dropPosition - Number(dropPos[dropPos.length - 1]);
+
+    const data = [...treeData];
+    const loop = (data, key, callback) => {
+      data.forEach((item, ind, arr) => {
+        if (item.key === key) return callback(item, ind, arr);
+        if (item.children) return loop(item.children, key, callback);
+      });
+    };
+
+    let dragObj;
+    loop(data, dragKey, (item, ind, arr) => {
+      arr.splice(ind, 1);
+      dragObj = item;
+    });
+
+    if (!dropToGap) {
+      loop(data, dropKey, (item, ind, arr) => {
+        item.children = item.children || [];
+        item.children.push(dragObj);
+      });
+    } else if (dropPosition === 1 && node.children && node.expanded) {
+      loop(data, dropKey, item => {
+        item.children = item.children || [];
+        item.children.unshift(dragObj);
+      });
+    } else {
+      let dropNodeInd;
+      let dropNodePosArr;
+      loop(data, dropKey, (item, ind, arr) => {
+        dropNodePosArr = arr;
+        dropNodeInd = ind;
+      });
+      if (dropPosition === -1) {
+        dropNodePosArr.splice(dropNodeInd, 0, dragObj);
+      } else {
+        dropNodePosArr.splice(dropNodeInd + 1, 0, dragObj);
+      }
     }
-);
+    setTreeData(data);
+  };
+
+  const findDescendantKeys = node => {
+    let res = [node.key];
+    const findChild = item => {
+      if (!item) return;
+      const { children } = item;
+
+      if (children && children.length) {
+        children.forEach(child => {
+          res.push(child.key);
+          findChild(child);
+        });
+      }
+    };
+    findChild(node);
+    return res;
+  };
+
+  const handleSelect = (key, bool, node) => {
+    setSelected(new Set([key]));
+    const descendantKeys = findDescendantKeys(node);
+    setSelectedThroughParent(new Set(descendantKeys));
+  };
+
+  const renderLabel = ({ className, data, onClick, expandIcon }) => {
+    const { label, icon, key } = data;
+    const isLeaf = !(data.children && data.children.length);
+    const style = {
+      backgroundColor: selected.has(key)
+        ? 'rgba(var(--semi-blue-0), 1)'
+        : selectedThroughParent.has(key)
+        ? 'rgba(var(--semi-blue-0), .5)'
+        : 'transparent',
+    };
+    return (
+      <li className={className} role="treenode" onClick={onClick} style={style}>
+        {isLeaf ? <span style={{ width: 24 }}></span> : expandIcon}
+        {icon ? icon : null}
+        <span>{label}</span>
+      </li>
+    );
+  };
+
+  const treeStyle = {
+    height: 420,
+    border: '1px solid var(--semi-color-border)',
+  };
+
+  return (
+    <Tree
+      treeData={treeData}
+      draggable
+      onDrop={onDrop}
+      renderFullLabel={renderLabel}
+      onSelect={handleSelect}
+      style={treeStyle}
+      defaultExpandAll
+    />
+  );
+};
+
+RenderFullLabelWithDraggable.story = {
+  name: 'renderFullLabel with draggable',
+};

Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно