Repository: IduxFE/components
Pull request #39 (2020-12-18 13:40:44)

refactor(comp:icon): add wapper class and inner static icons
## PR Checklist

Please check if your PR fulfills the following requirements:

- [x] The commit message follows [our guidelines](https://github.com/IduxFE/components/blob/main/docs/contributing.zh.md#commit)
- [x] Tests for the changes have been added/updated or not needed
- [x] Docs and demo have been added/updated or not needed

## PR Type

What kind of change does this PR introduce?

- [ ] Bugfix
- [ ] Feature
- [ ] Component style update
- [ ] Code style update (formatting, local variables)
- [x] Refactoring (no functional changes, no api changes)
- [ ] Build related changes
- [ ] CI related changes
- [ ] Documentation content changes
- [ ] Application (the showcase website) / infrastructure changes
- [ ] Other... Please describe:

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying, or link to a relevant issue. -->

## What is the new behavior?

## Other information


codecov[bot]: # [Codecov](https://codecov.io/gh/IduxFE/components/pull/39?src=pr&el=h1) Report
> Merging [#39](https://codecov.io/gh/IduxFE/components/pull/39?src=pr&el=desc) (91d6956) into [main](https://codecov.io/gh/IduxFE/components/commit/1fe6eb71bdb7b2d8a4924563d5e8f6acfc5798e4?el=desc) (1fe6eb7) will **increase** coverage by `0.28%`.
> The diff coverage is `100.00%`.

[![Impacted file tree graph](https://codecov.io/gh/IduxFE/components/pull/39/graphs/tree.svg?width=650&height=150&src=pr&token=PGAUXP06V3)](https://codecov.io/gh/IduxFE/components/pull/39?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##             main      #39      +/-   ##
==========================================
+ Coverage   93.13%   93.41%   +0.28%     
==========================================
  Files          16       21       +5     
  Lines         233      243      +10     
  Branches       35       37       +2     
==========================================
+ Hits          217      227      +10     
  Misses          7        7              
  Partials        9        9              
```


| [Impacted Files](https://codecov.io/gh/IduxFE/components/pull/39?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [packages/components/icon/definitions/down.ts](https://codecov.io/gh/IduxFE/components/pull/39/diff?src=pr&el=tree#diff-cGFja2FnZXMvY29tcG9uZW50cy9pY29uL2RlZmluaXRpb25zL2Rvd24udHM=) | `100.00% <100.00%> (ø)` | |
| [packages/components/icon/definitions/left.ts](https://codecov.io/gh/IduxFE/components/pull/39/diff?src=pr&el=tree#diff-cGFja2FnZXMvY29tcG9uZW50cy9pY29uL2RlZmluaXRpb25zL2xlZnQudHM=) | `100.00% <100.00%> (ø)` | |
| [packages/components/icon/definitions/loading.ts](https://codecov.io/gh/IduxFE/components/pull/39/diff?src=pr&el=tree#diff-cGFja2FnZXMvY29tcG9uZW50cy9pY29uL2RlZmluaXRpb25zL2xvYWRpbmcudHM=) | `100.00% <100.00%> (ø)` | |
| [packages/components/icon/definitions/right.ts](https://codecov.io/gh/IduxFE/components/pull/39/diff?src=pr&el=tree#diff-cGFja2FnZXMvY29tcG9uZW50cy9pY29uL2RlZmluaXRpb25zL3JpZ2h0LnRz) | `100.00% <100.00%> (ø)` | |
| [packages/components/icon/definitions/up.ts](https://codecov.io/gh/IduxFE/components/pull/39/diff?src=pr&el=tree#diff-cGFja2FnZXMvY29tcG9uZW50cy9pY29uL2RlZmluaXRpb25zL3VwLnRz) | `100.00% <100.00%> (ø)` | |
| [packages/components/icon/index.ts](https://codecov.io/gh/IduxFE/components/pull/39/diff?src=pr&el=tree#diff-cGFja2FnZXMvY29tcG9uZW50cy9pY29uL2luZGV4LnRz) | `100.00% <100.00%> (ø)` | |
| [packages/components/icon/src/Icon.vue](https://codecov.io/gh/IduxFE/components/pull/39/diff?src=pr&el=tree#diff-cGFja2FnZXMvY29tcG9uZW50cy9pY29uL3NyYy9JY29uLnZ1ZQ==) | `97.67% <100.00%> (+0.23%)` | :arrow_up: |
| [packages/components/icon/src/icons.ts](https://codecov.io/gh/IduxFE/components/pull/39/diff?src=pr&el=tree#diff-cGFja2FnZXMvY29tcG9uZW50cy9pY29uL3NyYy9pY29ucy50cw==) | `100.00% <100.00%> (ø)` | |
| ... and [4 more](https://codecov.io/gh/IduxFE/components/pull/39/diff?src=pr&el=tree-more) | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/IduxFE/components/pull/39?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/IduxFE/components/pull/39?src=pr&el=footer). Last update [1fe6eb7...4efdf5a](https://codecov.io/gh/IduxFE/components/pull/39?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/.gitignore b/.gitignore
index 3ed4034d..540eef41 100644
--- a/.gitignore
+++ b/.gitignore
@@ -15,5 +15,4 @@ package-lock.json
 yarn.lock
 
 # temp icons
-packages/components/icon/src/svg
-packages/components/icon/src/definitions
+scripts/gulp/icons/assets
diff --git a/.prettierignore b/.prettierignore
index caa0b08f..49a8719c 100644
--- a/.prettierignore
+++ b/.prettierignore
@@ -11,7 +11,3 @@ output/
 package.json
 package-lock.json
 yarn.lock
-
-# temp icons
-packages/components/icon/src/svg
-packages/components/icon/src/definitions
diff --git a/packages/components/icon/definitions/down.ts b/packages/components/icon/definitions/down.ts
new file mode 100644
index 00000000..cf51f58d
--- /dev/null
+++ b/packages/components/icon/definitions/down.ts
@@ -0,0 +1,5 @@
+export const Down = {
+  name: 'down',
+  svgString:
+    '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024"><path d="M265.827 438.627l224.22 224.22c12.497 12.496 32.758 12.496 45.255 0l222.871-222.871c12.496-12.497 12.496-32.758 0-45.255-12.497-12.497-32.758-12.497-45.255 0L521.725 585.914c-4.999 4.998-13.103 4.998-18.102 0L311.082 393.373c-12.497-12.497-32.758-12.497-45.255 0-12.496 12.496-12.496 32.758 0 45.254z"/></svg>',
+}
diff --git a/packages/components/icon/definitions/index.ts b/packages/components/icon/definitions/index.ts
new file mode 100644
index 00000000..3de9c7b8
--- /dev/null
+++ b/packages/components/icon/definitions/index.ts
@@ -0,0 +1,5 @@
+export * from './down'
+export * from './left'
+export * from './loading'
+export * from './right'
+export * from './up'
diff --git a/packages/components/icon/definitions/left.ts b/packages/components/icon/definitions/left.ts
new file mode 100644
index 00000000..a01954c8
--- /dev/null
+++ b/packages/components/icon/definitions/left.ts
@@ -0,0 +1,5 @@
+export const Left = {
+  name: 'left',
+  svgString:
+    '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1025 1024"><path d="M585.592 758.173l-224.219-224.22c-12.497-12.497-12.497-32.758 0-45.255l222.871-222.871c12.496-12.496 32.758-12.496 45.254 0 12.497 12.497 12.497 32.758 0 45.255L438.306 502.275c-4.999 4.999-4.999 13.103 0 18.102l192.541 192.541c12.496 12.497 12.496 32.758 0 45.255-12.497 12.496-32.758 12.496-45.255 0z"/></svg>',
+}
diff --git a/packages/components/icon/definitions/loading.ts b/packages/components/icon/definitions/loading.ts
new file mode 100644
index 00000000..072ad1dd
--- /dev/null
+++ b/packages/components/icon/definitions/loading.ts
@@ -0,0 +1,5 @@
+export const Loading = {
+  name: 'loading',
+  svgString:
+    '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024"><defs><style/></defs><path d="M384 170.666c0-70.688 57.312-128 128-128s128 57.312 128 128-57.312 128-128 128-128-57.312-128-128zm271.52 112.48c0-70.688 57.312-128 128-128s128 57.312 128 128-57.312 128-128 128-128-57.312-128-128zM832 554.666c0-35.36 28.64-64 64-64s64 28.64 64 64-28.64 64-64 64-64-28.64-64-64zm-112.48 271.52c0-35.36 28.64-64 64-64s64 28.64 64 64-28.64 64-64 64-64-28.64-64-64zM448 938.666c0-35.36 28.64-64 64-64s64 28.64 64 64-28.64 64-64 64-64-28.64-64-64zm-271.52-112.48c0-35.36 28.64-64 64-64s64 28.64 64 64-28.64 64-64 64-64-28.64-64-64zm-32-543.04c0-53.024 42.976-96 96-96s96 42.976 96 96-42.976 96-96 96-96-42.976-96-96zM56 554.666c0-39.776 32.224-72 72-72s72 32.224 72 72-32.224 72-72 72-72-32.224-72-72z"/></svg>',
+}
diff --git a/packages/components/icon/definitions/right.ts b/packages/components/icon/definitions/right.ts
new file mode 100644
index 00000000..a6d078e9
--- /dev/null
+++ b/packages/components/icon/definitions/right.ts
@@ -0,0 +1,5 @@
+export const Right = {
+  name: 'right',
+  svgString:
+    '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1025 1024"><path d="M438.627 758.173l224.22-224.22c12.496-12.497 12.496-32.758 0-45.255L439.976 265.827c-12.497-12.496-32.758-12.496-45.255 0-12.497 12.497-12.497 32.758 0 45.255l191.193 191.193c4.998 4.999 4.998 13.103 0 18.102L393.373 712.918c-12.497 12.497-12.497 32.758 0 45.255 12.496 12.496 32.758 12.496 45.254 0z"/></svg>',
+}
diff --git a/packages/components/icon/definitions/up.ts b/packages/components/icon/definitions/up.ts
new file mode 100644
index 00000000..8298ec50
--- /dev/null
+++ b/packages/components/icon/definitions/up.ts
@@ -0,0 +1,5 @@
+export const Up = {
+  name: 'up',
+  svgString:
+    '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024"><path d="M265.827 617.592l224.22-224.219c12.497-12.497 32.758-12.497 45.255 0l222.871 222.871c12.496 12.496 12.496 32.758 0 45.254-12.497 12.497-32.758 12.497-45.255 0L521.725 470.306c-4.999-4.999-13.103-4.999-18.102 0L311.082 662.847c-12.497 12.497-32.758 12.497-45.255 0-12.496-12.497-12.496-32.758 0-45.255z"/></svg>',
+}
diff --git a/packages/components/icon/demo/basic.md b/packages/components/icon/demo/basic.md
index 6c5ec25d..00906fa4 100644
--- a/packages/components/icon/demo/basic.md
+++ b/packages/components/icon/demo/basic.md
@@ -26,7 +26,8 @@ title:
 <script lang="ts">
 import { defineComponent } from 'vue'
 import { useGlobalConfig } from '@idux/components'
-import { addIconDefinitions, Down, fetchFromIconfont } from '@idux/components/icon'
+import { addIconDefinitions,  fetchFromIconfont } from '@idux/components'
+import { Down } from '@idux/components/icon/definitions'
 
 export default defineComponent({
   setup() {
@@ -36,7 +37,7 @@ export default defineComponent({
     // 动态加载：不会被打包，可以减小包体积，需要加载的时候时候 http 请求加载
     const loadIconDynamically = (iconName: string) => {
       // TODO： fix with vite
-      return fetch(`packages/components/icon/src/svg/${iconName}.svg`).then(res => res.text())
+      return fetch(`packages/components/icon/svg/${iconName}.svg`).then(res => res.text())
     }
     useGlobalConfig('icon', { loadIconDynamically })
 
diff --git a/packages/components/icon/index.ts b/packages/components/icon/index.ts
index d146877d..51e8c361 100644
--- a/packages/components/icon/index.ts
+++ b/packages/components/icon/index.ts
@@ -1,9 +1,11 @@
 import { installComponent } from '@idux/components/core/utils'
 import IxIcon from './src/Icon.vue'
+import { addIconDefinitions, fetchFromIconfont } from './src/helper'
+import { innerStaticIcons } from './src/icons'
+
+addIconDefinitions(innerStaticIcons)
 
 IxIcon.install = installComponent(IxIcon)
 
-export { IxIcon }
+export { IxIcon, addIconDefinitions, fetchFromIconfont }
 export type { IconComponent, IconDefinition } from './src/types'
-export * from './src/helper'
-export * from './src/definitions'
diff --git a/packages/components/icon/src/Icon.vue b/packages/components/icon/src/Icon.vue
index c0f710c3..43647529 100644
--- a/packages/components/icon/src/Icon.vue
+++ b/packages/components/icon/src/Icon.vue
@@ -1,5 +1,5 @@
 <template>
-  <component :is="tag" ref="root" class="ix-icon" :class="{ 'ix-icon-spin': isSpin }" role="img" :ariaLabel="name">
+  <component :is="tag" ref="root" :class="classes" role="img" :ariaLabel="name">
     <slot></slot>
   </component>
 </template>
@@ -32,9 +32,8 @@ export default defineComponent({
       tag.value = attrs.onClick ? 'button' : 'i'
     })
 
-    const isSpin = computed(() => typeof props.rotate === 'boolean' && props.rotate)
-
-    return { root, tag, isSpin }
+    const classes = useClasses(props)
+    return { root, tag, classes }
   },
 })
 
@@ -77,4 +76,11 @@ function handleRotate(svg: SVGElement, rotate?: number | string | boolean): void
     svg.removeAttribute('style')
   }
 }
+
+const useClasses = (props: IconProps) => {
+  return computed(() => {
+    const isSpin = props.name === 'loading' || (typeof props.rotate === 'boolean' && props.rotate)
+    return ['ix-icon', props.name ? `ix-icon-${props.name}` : '', isSpin ? 'ix-icon-spin' : '']
+  })
+}
 </script>
diff --git a/packages/components/icon/src/definitions/index.ts b/packages/components/icon/src/definitions/index.ts
deleted file mode 100644
index 518343ac..00000000
--- a/packages/components/icon/src/definitions/index.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-// placeholder for pass test
-export const __Placeholder = null
diff --git a/packages/components/icon/src/icons.ts b/packages/components/icon/src/icons.ts
new file mode 100644
index 00000000..3b569b51
--- /dev/null
+++ b/packages/components/icon/src/icons.ts
@@ -0,0 +1,4 @@
+import { Down, Left, Loading, Right, Up } from '../definitions'
+import { IconDefinition } from './types'
+
+export const innerStaticIcons: IconDefinition[] = [Up, Down, Left, Right, Loading]
diff --git a/packages/components/icon/svg/down.svg b/packages/components/icon/svg/down.svg
new file mode 100644
index 00000000..ba5444f9
--- /dev/null
+++ b/packages/components/icon/svg/down.svg
@@ -0,0 +1,1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024"><path d="M265.827 438.627l224.22 224.22c12.497 12.496 32.758 12.496 45.255 0l222.871-222.871c12.496-12.497 12.496-32.758 0-45.255-12.497-12.497-32.758-12.497-45.255 0L521.725 585.914c-4.999 4.998-13.103 4.998-18.102 0L311.082 393.373c-12.497-12.497-32.758-12.497-45.255 0-12.496 12.496-12.496 32.758 0 45.254z"/></svg>
\ No newline at end of file
diff --git a/packages/components/icon/svg/left.svg b/packages/components/icon/svg/left.svg
new file mode 100644
index 00000000..b69c7680
--- /dev/null
+++ b/packages/components/icon/svg/left.svg
@@ -0,0 +1,1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1025 1024"><path d="M585.592 758.173l-224.219-224.22c-12.497-12.497-12.497-32.758 0-45.255l222.871-222.871c12.496-12.496 32.758-12.496 45.254 0 12.497 12.497 12.497 32.758 0 45.255L438.306 502.275c-4.999 4.999-4.999 13.103 0 18.102l192.541 192.541c12.496 12.497 12.496 32.758 0 45.255-12.497 12.496-32.758 12.496-45.255 0z"/></svg>
\ No newline at end of file
diff --git a/packages/components/icon/svg/loading.svg b/packages/components/icon/svg/loading.svg
new file mode 100644
index 00000000..82154fb1
--- /dev/null
+++ b/packages/components/icon/svg/loading.svg
@@ -0,0 +1,1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024"><defs><style/></defs><path d="M384 170.666c0-70.688 57.312-128 128-128s128 57.312 128 128-57.312 128-128 128-128-57.312-128-128zm271.52 112.48c0-70.688 57.312-128 128-128s128 57.312 128 128-57.312 128-128 128-128-57.312-128-128zM832 554.666c0-35.36 28.64-64 64-64s64 28.64 64 64-28.64 64-64 64-64-28.64-64-64zm-112.48 271.52c0-35.36 28.64-64 64-64s64 28.64 64 64-28.64 64-64 64-64-28.64-64-64zM448 938.666c0-35.36 28.64-64 64-64s64 28.64 64 64-28.64 64-64 64-64-28.64-64-64zm-271.52-112.48c0-35.36 28.64-64 64-64s64 28.64 64 64-28.64 64-64 64-64-28.64-64-64zm-32-543.04c0-53.024 42.976-96 96-96s96 42.976 96 96-42.976 96-96 96-96-42.976-96-96zM56 554.666c0-39.776 32.224-72 72-72s72 32.224 72 72-32.224 72-72 72-72-32.224-72-72z"/></svg>
\ No newline at end of file
diff --git a/packages/components/icon/svg/right.svg b/packages/components/icon/svg/right.svg
new file mode 100644
index 00000000..1de61c5f
--- /dev/null
+++ b/packages/components/icon/svg/right.svg
@@ -0,0 +1,1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1025 1024"><path d="M438.627 758.173l224.22-224.22c12.496-12.497 12.496-32.758 0-45.255L439.976 265.827c-12.497-12.496-32.758-12.496-45.255 0-12.497 12.497-12.497 32.758 0 45.255l191.193 191.193c4.998 4.999 4.998 13.103 0 18.102L393.373 712.918c-12.497 12.497-12.497 32.758 0 45.255 12.496 12.496 32.758 12.496 45.254 0z"/></svg>
\ No newline at end of file
diff --git a/packages/components/icon/svg/up.svg b/packages/components/icon/svg/up.svg
new file mode 100644
index 00000000..d3b3c8ef
--- /dev/null
+++ b/packages/components/icon/svg/up.svg
@@ -0,0 +1,1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024"><path d="M265.827 617.592l224.22-224.219c12.497-12.497 32.758-12.497 45.255 0l222.871 222.871c12.496 12.496 12.496 32.758 0 45.254-12.497 12.497-32.758 12.497-45.255 0L521.725 470.306c-4.999-4.999-13.103-4.999-18.102 0L311.082 662.847c-12.497 12.497-32.758 12.497-45.255 0-12.496-12.497-12.496-32.758 0-45.255z"/></svg>
\ No newline at end of file
diff --git a/packages/components/index.ts b/packages/components/index.ts
index 1a2ea278..366482b7 100644
--- a/packages/components/index.ts
+++ b/packages/components/index.ts
@@ -21,5 +21,4 @@ export * from './core/config'
 export * from './core/types'
 
 export * from './button'
-export { IxIcon } from './icon'
-export type { IconComponent, IconDefinition } from './icon'
+export * from './icon'
diff --git a/scripts/gulp/icons/assets/angle-down.svg b/scripts/gulp/icons/assets/angle-down.svg
deleted file mode 100644
index 5ddc2490..00000000
--- a/scripts/gulp/icons/assets/angle-down.svg
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" standalone="no"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg class="icon"
-    width="200px" height="200.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg">
-    <path fill="#333333" d="M256.70631 383.835161h447.562927l-223.781463 255.750244-223.781464-255.750244z" />
-</svg>
\ No newline at end of file
diff --git a/scripts/gulp/icons/assets/angle-left.svg b/scripts/gulp/icons/assets/angle-left.svg
deleted file mode 100644
index 2ee8300a..00000000
--- a/scripts/gulp/icons/assets/angle-left.svg
+++ /dev/null
@@ -1,1 +0,0 @@
-<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="200px" height="200.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path fill="#333333" d="M640 736V288L384 512l256 224z" /></svg>
\ No newline at end of file
diff --git a/scripts/gulp/icons/assets/angle-right.svg b/scripts/gulp/icons/assets/angle-right.svg
deleted file mode 100644
index ca319cbb..00000000
--- a/scripts/gulp/icons/assets/angle-right.svg
+++ /dev/null
@@ -1,1 +0,0 @@
-<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="200px" height="200.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path fill="#333333" d="M384 288v448l256-224-256-224z" /></svg>
\ No newline at end of file
diff --git a/scripts/gulp/icons/assets/angle-up.svg b/scripts/gulp/icons/assets/angle-up.svg
deleted file mode 100644
index 3ee2c21f..00000000
--- a/scripts/gulp/icons/assets/angle-up.svg
+++ /dev/null
@@ -1,1 +0,0 @@
-<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="200px" height="200.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path fill="#333333" d="M256 640h448L480 384 256 640z" /></svg>
\ No newline at end of file
diff --git a/scripts/gulp/icons/assets/double-down.svg b/scripts/gulp/icons/assets/double-down.svg
deleted file mode 100644
index 2c2dd514..00000000
--- a/scripts/gulp/icons/assets/double-down.svg
+++ /dev/null
@@ -1,1 +0,0 @@
-<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="200px" height="200.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path fill="#333333" d="M266.782 534.127l224.22 224.22c12.496 12.497 32.758 12.497 45.254 0l222.871-222.871c12.497-12.497 12.497-32.758 0-45.255-12.496-12.497-32.758-12.497-45.254 0L522.68 681.414c-4.999 4.998-13.103 4.998-18.102 0l-192.54-192.541c-12.498-12.497-32.759-12.497-45.256 0-12.497 12.496-12.497 32.758 0 45.254z m0-224l224.22 224.22c12.496 12.497 32.758 12.497 45.254 0l222.871-222.871c12.497-12.497 12.497-32.758 0-45.255-12.496-12.497-32.758-12.497-45.254 0L522.68 457.414c-4.999 4.998-13.103 4.998-18.102 0l-192.54-192.541c-12.498-12.497-32.759-12.497-45.256 0-12.497 12.496-12.497 32.758 0 45.254z" /></svg>
\ No newline at end of file
diff --git a/scripts/gulp/icons/assets/double-left.svg b/scripts/gulp/icons/assets/double-left.svg
deleted file mode 100644
index 7b67a5be..00000000
--- a/scripts/gulp/icons/assets/double-left.svg
+++ /dev/null
@@ -1,1 +0,0 @@
-<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="200px" height="200.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path fill="#333333" d="M489.621 758.173l-224.219-224.22c-12.497-12.497-12.497-32.758 0-45.255l222.871-222.871c12.497-12.496 32.758-12.496 45.255 0 12.496 12.497 12.496 32.758 0 45.255L342.335 502.275c-4.999 4.999-4.999 13.103 0 18.102l192.541 192.541c12.497 12.497 12.497 32.758 0 45.255-12.497 12.496-32.758 12.496-45.255 0z m224 0l-224.219-224.22c-12.497-12.497-12.497-32.758 0-45.255l222.871-222.871c12.497-12.496 32.758-12.496 45.255 0 12.496 12.497 12.496 32.758 0 45.255L566.335 502.275c-4.999 4.999-4.999 13.103 0 18.102l192.541 192.541c12.497 12.497 12.497 32.758 0 45.255-12.497 12.496-32.758 12.496-45.255 0z" /></svg>
\ No newline at end of file
diff --git a/scripts/gulp/icons/assets/double-right.svg b/scripts/gulp/icons/assets/double-right.svg
deleted file mode 100644
index 9d028f51..00000000
--- a/scripts/gulp/icons/assets/double-right.svg
+++ /dev/null
@@ -1,1 +0,0 @@
-<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="200px" height="200.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path fill="#333333" d="M535.584 758.173l224.22-224.22c12.496-12.497 12.496-32.758 0-45.255L536.933 265.827c-12.497-12.496-32.758-12.496-45.255 0-12.497 12.497-12.497 32.758 0 45.255L682.87 502.275c4.999 4.999 4.999 13.103 0 18.102L490.33 712.918c-12.497 12.497-12.497 32.758 0 45.255 12.496 12.496 32.758 12.496 45.254 0z m-224 0l224.22-224.22c12.496-12.497 12.496-32.758 0-45.255L312.933 265.827c-12.497-12.496-32.758-12.496-45.255 0-12.497 12.497-12.497 32.758 0 45.255L458.87 502.275c4.999 4.999 4.999 13.103 0 18.102L266.33 712.918c-12.497 12.497-12.497 32.758 0 45.255 12.496 12.496 32.758 12.496 45.254 0z" /></svg>
\ No newline at end of file
diff --git a/scripts/gulp/icons/assets/double-up.svg b/scripts/gulp/icons/assets/double-up.svg
deleted file mode 100644
index 1f92a56b..00000000
--- a/scripts/gulp/icons/assets/double-up.svg
+++ /dev/null
@@ -1,1 +0,0 @@
-<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="200px" height="200.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path fill="#333333" d="M266.782 489.092l224.22-224.22c12.496-12.496 32.758-12.496 45.254 0l222.871 222.872c12.497 12.496 12.497 32.758 0 45.254-12.496 12.497-32.758 12.497-45.254 0L522.68 341.806c-4.999-4.999-13.103-4.999-18.102 0l-192.54 192.54c-12.498 12.498-32.759 12.498-45.256 0-12.497-12.496-12.497-32.757 0-45.254z m0 224l224.22-224.22c12.496-12.496 32.758-12.496 45.254 0l222.871 222.872c12.497 12.496 12.497 32.758 0 45.254-12.496 12.497-32.758 12.497-45.254 0L522.68 565.806c-4.999-4.999-13.103-4.999-18.102 0l-192.54 192.54c-12.498 12.498-32.759 12.498-45.256 0-12.497-12.496-12.497-32.757 0-45.254z" /></svg>
\ No newline at end of file
diff --git a/scripts/gulp/icons/assets/loading.svg b/scripts/gulp/icons/assets/loading.svg
new file mode 100644
index 00000000..f0d8db38
--- /dev/null
+++ b/scripts/gulp/icons/assets/loading.svg
@@ -0,0 +1,1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1608296485362" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5578" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M384 170.666c0-70.688 57.312-128 128-128s128 57.312 128 128-57.312 128-128 128-128-57.312-128-128z m271.52 112.48c0-70.688 57.312-128 128-128s128 57.312 128 128-57.312 128-128 128-128-57.312-128-128zM832 554.666c0-35.36 28.64-64 64-64s64 28.64 64 64-28.64 64-64 64-64-28.64-64-64z m-112.48 271.52c0-35.36 28.64-64 64-64s64 28.64 64 64-28.64 64-64 64-64-28.64-64-64zM448 938.666c0-35.36 28.64-64 64-64s64 28.64 64 64-28.64 64-64 64-64-28.64-64-64z m-271.52-112.48c0-35.36 28.64-64 64-64s64 28.64 64 64-28.64 64-64 64-64-28.64-64-64z m-32-543.04c0-53.024 42.976-96 96-96s96 42.976 96 96-42.976 96-96 96-96-42.976-96-96zM56 554.666c0-39.776 32.224-72 72-72s72 32.224 72 72-32.224 72-72 72-72-32.224-72-72z" p-id="5579"></path></svg>
\ No newline at end of file
diff --git a/scripts/gulp/icons/assets/menu-collapsed.svg b/scripts/gulp/icons/assets/menu-collapsed.svg
deleted file mode 100644
index 6b9f4a1f..00000000
--- a/scripts/gulp/icons/assets/menu-collapsed.svg
+++ /dev/null
@@ -1,1 +0,0 @@
-<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="200px" height="200.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path fill="#333333" d="M96 192h832c17.673 0 32 14.327 32 32 0 17.673-14.327 32-32 32H96c-17.673 0-32-14.327-32-32 0-17.673 14.327-32 32-32z m0 640h832c17.673 0 32 14.327 32 32 0 17.673-14.327 32-32 32H96c-17.673 0-32-14.327-32-32 0-17.673 14.327-32 32-32z m0-320h448c17.673 0 32 14.327 32 32 0 17.673-14.327 32-32 32H96c-17.673 0-32-14.327-32-32 0-17.673 14.327-32 32-32z m683.8 41.833a12.753 12.753 0 0 1-1.639-1.639c-4.526-5.43-3.792-13.502 1.639-18.027l159.206-132.672c2.3-1.917 5.2-2.966 8.194-2.966 7.069 0 12.8 5.73 12.8 12.8v265.343a12.8 12.8 0 0 1-2.967 8.194c-4.525 5.431-12.597 6.164-18.027 1.639L779.8 553.833z" /></svg>
\ No newline at end of file
diff --git a/scripts/gulp/icons/assets/menu-expanded.svg b/scripts/gulp/icons/assets/menu-expanded.svg
deleted file mode 100644
index 7ec06694..00000000
--- a/scripts/gulp/icons/assets/menu-expanded.svg
+++ /dev/null
@@ -1,1 +0,0 @@
-<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="200px" height="200.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path fill="#333333" d="M96 192h832c17.673 0 32 14.327 32 32 0 17.673-14.327 32-32 32H96c-17.673 0-32-14.327-32-32 0-17.673 14.327-32 32-32z m0 640h832c17.673 0 32 14.327 32 32 0 17.673-14.327 32-32 32H96c-17.673 0-32-14.327-32-32 0-17.673 14.327-32 32-32z m0-320h448c17.673 0 32 14.327 32 32 0 17.673-14.327 32-32 32H96c-17.673 0-32-14.327-32-32 0-17.673 14.327-32 32-32z m852.2 41.833L788.994 686.505c-5.43 4.525-13.502 3.792-18.027-1.639a12.8 12.8 0 0 1-2.967-8.194V411.328c0-7.069 5.731-12.8 12.8-12.8a12.8 12.8 0 0 1 8.194 2.967L948.2 534.167c5.431 4.525 6.165 12.597 1.639 18.027a12.753 12.753 0 0 1-1.639 1.639z" /></svg>
\ No newline at end of file
diff --git a/scripts/gulp/icons/index.ts b/scripts/gulp/icons/index.ts
index 67b380a3..ea0d244a 100644
--- a/scripts/gulp/icons/index.ts
+++ b/scripts/gulp/icons/index.ts
@@ -4,17 +4,15 @@ import { join } from 'path'
 import SVGO from 'svgo'
 import { buildConfig } from '../buildConfig'
 
-const definitionTemplate = `import { IconDefinition } from '../types'
-
-export const {{definitionName}}: IconDefinition = {
+const definitionTemplate = `export const {{definitionName}} = {
   name: '{{name}}',
   svgString: '{{svgString}}',
 }
 `
 const { packageRoot } = buildConfig
 const assetsDirname = join(__dirname, 'assets')
-const outputAssetsDirname = join(packageRoot, 'components/icon/src/svg')
-const outputDefinitionsDirname = join(packageRoot, 'components/icon/src/definitions')
+const outputAssetsDirname = join(packageRoot, 'components/icon/svg')
+const outputDefinitionsDirname = join(packageRoot, 'components/icon/definitions')
 const outputDefinitionNames: string[] = []
 
 const options: SVGO.Options = {
@@ -34,7 +32,7 @@ export async function generateIcons(): Promise<void> {
   })
   await Promise.all(outputIcons)
 
-  const indexContent = outputDefinitionNames.map(item => `export * from './${item}'`).join('\n')
+  const indexContent = outputDefinitionNames.map(item => `export * from './${item}'`).join('\n') + '\n'
   writeFileSync(join(outputDefinitionsDirname, `index.ts`), indexContent, 'utf8')
 }
 


Test patch:
diff --git a/packages/components/button/__tests__/button.spec.ts b/packages/components/button/__tests__/button.spec.ts
index 9e6d090d..bef18cf6 100644
--- a/packages/components/button/__tests__/button.spec.ts
+++ b/packages/components/button/__tests__/button.spec.ts
@@ -1,28 +1,14 @@
-import { addIconDefinitions, IconDefinition } from '@idux/components/icon'
-import { flushPromises, mount, MountingOptions, VueWrapper } from '@vue/test-utils'
+import { mount, MountingOptions, VueWrapper } from '@vue/test-utils'
 import { DefineComponent } from 'vue'
 import Button from '../src/Button.vue'
 import { ButtonProps } from '../src/types'
 
-const Up: IconDefinition = {
-  name: 'up',
-  svgString:
-    '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024"><path d="M265.827 617.592l224.22-224.219c12.497-12.497 32.758-12.497 45.255 0l222.871 222.871c12.496 12.496 12.496 32.758 0 45.254-12.497 12.497-32.758 12.497-45.255 0L521.725 470.306c-4.999-4.999-13.103-4.999-18.102 0L311.082 662.847c-12.497 12.497-32.758 12.497-45.255 0-12.496-12.497-12.496-32.758 0-45.255z"/></svg>',
-}
-
-const Loading: IconDefinition = {
-  name: 'loading',
-  svgString:
-    '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024"><path d="M265.827 438.627l224.22 224.22c12.497 12.496 32.758 12.496 45.255 0l222.871-222.871c12.496-12.497 12.496-32.758 0-45.255-12.497-12.497-32.758-12.497-45.255 0L521.725 585.914c-4.999 4.998-13.103 4.998-18.102 0L311.082 393.373c-12.497-12.497-32.758-12.497-45.255 0-12.496 12.496-12.496 32.758 0 45.254z"/></svg>',
-}
-
 describe('Button.vue', () => {
   let buttonMount: (
     options?: MountingOptions<Partial<ButtonProps>>,
   ) => VueWrapper<InstanceType<DefineComponent<ButtonProps>>>
 
   beforeEach(() => {
-    addIconDefinitions([Up, Loading])
     buttonMount = (options = {}) => {
       return mount<ButtonProps>(Button, {
         ...options,
@@ -84,10 +70,9 @@ describe('Button.vue', () => {
 
   test.only('loading work', async () => {
     const wrapper = buttonMount({ props: { icon: 'up', loading: true } })
-    await flushPromises()
 
-    expect(wrapper.findAll('svg').length).toEqual(1)
-    expect(wrapper.find('svg').attributes()['data-icon']).toEqual('loading')
+    expect(wrapper.findAll('.ix-icon').length).toEqual(1)
+    expect(wrapper.find('.ix-icon-loading').exists()).toBeTruthy()
     expect(wrapper.classes()).toContain('ix-button-loading')
   })
 
@@ -125,14 +110,12 @@ describe('Button.vue', () => {
 
   test.only('icon work', async () => {
     const wrapper = buttonMount({ props: { icon: 'up' } })
-    await flushPromises()
 
-    expect(wrapper.find('svg').attributes()['data-icon']).toEqual('up')
+    expect(wrapper.find('.ix-icon-up').exists()).toBeTruthy()
 
-    await wrapper.setProps({ icon: 'loading' })
-    await flushPromises()
+    await wrapper.setProps({ icon: 'down' })
 
-    expect(wrapper.find('svg').attributes()['data-icon']).toEqual('loading')
+    expect(wrapper.find('.ix-icon-down').exists()).toBeTruthy()
   })
 
   test('slot work', async () => {
diff --git a/packages/components/icon/__tests__/__snapshots__/icon.spec.ts.snap b/packages/components/icon/__tests__/__snapshots__/icon.spec.ts.snap
index cb9ce8da..2a24fc2b 100644
--- a/packages/components/icon/__tests__/__snapshots__/icon.spec.ts.snap
+++ b/packages/components/icon/__tests__/__snapshots__/icon.spec.ts.snap
@@ -1,3 +1,3 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
-exports[`Icon.vue render work 1`] = `"<i class=\\"ix-icon\\" role=\\"img\\" arialabel=\\"up\\"><svg xmlns=\\"http://www.w3.org/2000/svg\\" viewBox=\\"0 0 1024 1024\\" width=\\"1em\\" height=\\"1em\\" focusable=\\"false\\" aria-hidden=\\"true\\" data-icon=\\"up\\"><path d=\\"M265.827 617.592l224.22-224.219c12.497-12.497 32.758-12.497 45.255 0l222.871 222.871c12.496 12.496 12.496 32.758 0 45.254-12.497 12.497-32.758 12.497-45.255 0L521.725 470.306c-4.999-4.999-13.103-4.999-18.102 0L311.082 662.847c-12.497 12.497-32.758 12.497-45.255 0-12.496-12.497-12.496-32.758 0-45.255z\\"></path></svg></i>"`;
+exports[`Icon.vue render work 1`] = `"<i class=\\"ix-icon ix-icon-up\\" role=\\"img\\" arialabel=\\"up\\"><svg width=\\"1em\\" height=\\"1em\\" focusable=\\"false\\" aria-hidden=\\"true\\" data-icon=\\"up\\"></svg></i>"`;
diff --git a/packages/components/icon/__tests__/icon.spec.ts b/packages/components/icon/__tests__/icon.spec.ts
index d2433bbd..ea7e9a9f 100644
--- a/packages/components/icon/__tests__/icon.spec.ts
+++ b/packages/components/icon/__tests__/icon.spec.ts
@@ -5,17 +5,9 @@ import { addIconDefinitions, fetchFromIconfont } from '../src/helper'
 import Icon from '../src/Icon.vue'
 import { IconProps, IconDefinition } from '../src/types'
 
-const Up: IconDefinition = {
-  name: 'up',
-  svgString:
-    '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024"><path d="M265.827 617.592l224.22-224.219c12.497-12.497 32.758-12.497 45.255 0l222.871 222.871c12.496 12.496 12.496 32.758 0 45.254-12.497 12.497-32.758 12.497-45.255 0L521.725 470.306c-4.999-4.999-13.103-4.999-18.102 0L311.082 662.847c-12.497 12.497-32.758 12.497-45.255 0-12.496-12.497-12.496-32.758 0-45.255z"/></svg>',
-}
-
-const Down: IconDefinition = {
-  name: 'down',
-  svgString:
-    '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024"><path d="M265.827 438.627l224.22 224.22c12.497 12.496 32.758 12.496 45.255 0l222.871-222.871c12.496-12.497 12.496-32.758 0-45.255-12.497-12.497-32.758-12.497-45.255 0L521.725 585.914c-4.999 4.998-13.103 4.998-18.102 0L311.082 393.373c-12.497-12.497-32.758-12.497-45.255 0-12.496 12.496-12.496 32.758 0 45.254z"/></svg>',
-}
+const Up: IconDefinition = { name: 'up', svgString: '<svg></svg>' }
+const Down: IconDefinition = { name: 'down', svgString: '<svg></svg>' }
+const Loading: IconDefinition = { name: 'loading', svgString: '<svg></svg>' }
 
 describe('Icon.vue', () => {
   let IconMount: (options?: MountingOptions<Partial<IconProps>>) => VueWrapper<InstanceType<DefineComponent<IconProps>>>
@@ -49,15 +41,7 @@ describe('Icon.vue', () => {
   })
 
   test('dynamic load work', async () => {
-    const loadIconDynamically = async (iconName: string) => {
-      if (iconName === 'dynamic-up') {
-        return Up.svgString
-      } else if (iconName === 'dynamic-down') {
-        return Down.svgString
-      } else {
-        return ''
-      }
-    }
+    const loadIconDynamically = async (iconName: string) => `<svg data-icon="${iconName}"></svg>`
 
     const wrapper = mount({
       components: { Icon },
@@ -102,7 +86,7 @@ describe('Icon.vue', () => {
   })
 
   test('rotate work', async () => {
-    addIconDefinitions([Up])
+    addIconDefinitions([Up, Loading])
     const wrapper = IconMount({ props: { rotate: true } })
 
     expect(wrapper.classes()).toContain('ix-icon-spin')
@@ -113,8 +97,10 @@ describe('Icon.vue', () => {
     expect(wrapper.classes()).not.toContain('ix-icon-spin')
     expect(wrapper.find('svg').attributes()['style']).toEqual('transform: rotate(90deg)')
 
-    await wrapper.setProps({ rotate: '180' })
+    await wrapper.setProps({ name: 'loading', rotate: '180' })
+    await flushPromises()
 
+    expect(wrapper.classes()).toContain('ix-icon-spin')
     expect(wrapper.find('svg').attributes()['style']).toEqual('transform: rotate(180deg)')
   })
 
@@ -141,7 +127,6 @@ describe('Icon.vue', () => {
         default: Up.svgString,
       },
     })
-    await flushPromises()
     expect(wrapper.find('svg').exists()).toBeTruthy()
   })
 })