From 86c2c6742e3f35666b7851b3e4ef73b79f6637dd Mon Sep 17 00:00:00 2001
From: 07akioni <07akioni2@gmail.com>
Date: Sun, 18 Apr 2021 21:59:18 +0800
Subject: [PATCH] feat(message): clsPrefix

---
 src/_styles/common/light.ts                   |   8 +-
 src/drawer/demos/zhCN/dark-1-debug.demo.md    |   8 +-
 src/drawer/demos/zhCN/dark-3-debug.demo.md    |   6 -
 src/form/demos/enUS/change-debug.demo.md      |   8 +-
 .../demos/enUS/required-mark-debug.demo.md    |   8 +-
 src/form/demos/zhCN/height-debug.demo.md      |   8 +-
 src/form/demos/zhCN/validator-debug.demo.md   |   8 +-
 src/icon/src/Icon.ts                          |   4 +-
 src/input/demos/enUS/event.demo.md            |  41 ++---
 src/input/demos/enUS/pair.demo.md             |  39 ++---
 .../demos/enUS/passively-activated.demo.md    |  41 ++---
 src/input/demos/zhCN/event.demo.md            |  41 ++---
 src/input/demos/zhCN/pair.demo.md             |  39 ++---
 .../demos/zhCN/passively-activated.demo.md    |  41 ++---
 src/log/demos/enUS/event.demo.md              |  61 ++++----
 src/log/demos/enUS/scroll.demo.md             |  71 +++++----
 src/log/demos/zhCN/event.demo.md              |  61 ++++----
 src/log/demos/zhCN/scroll.demo.md             |  71 +++++----
 src/message/demos/enUS/icon.demo.md           |   2 +-
 src/message/demos/zhCN/icon.demo.md           |   2 +-
 src/message/index.ts                          |   3 +-
 src/message/src/{Message.ts => Message.tsx}   | 145 +++++++++---------
 ...eEnvironment.ts => MessageEnvironment.tsx} |  55 +++----
 ...MessageProvider.ts => MessageProvider.tsx} | 111 ++++++++------
 src/message/src/message-props.ts              |   9 +-
 src/message/src/styles/index.cssr.ts          |  23 ++-
 src/message/src/use-message.ts                |   7 +-
 src/modal/demos/zhCN/dark-1-debug.demo.md     |   8 +-
 src/modal/demos/zhCN/dark-3-debug.demo.md     |   6 -
 src/modal/demos/zhCN/dark-6-debug.demo.md     |   8 +-
 src/modal/demos/zhCN/dark-9-debug.demo.md     |   6 -
 src/modal/demos/zhCN/drawer-debug.demo.md     |   8 +-
 src/tabs/demos/enUS/card.demo.md              |  39 +++--
 src/tabs/demos/zhCN/card.demo.md              |  39 +++--
 34 files changed, 565 insertions(+), 470 deletions(-)
 rename src/message/src/{Message.ts => Message.tsx} (58%)
 rename src/message/src/{MessageEnvironment.ts => MessageEnvironment.tsx} (68%)
 rename src/message/src/{MessageProvider.ts => MessageProvider.tsx} (57%)

diff --git a/src/_styles/common/light.ts b/src/_styles/common/light.ts
index 062dfa085..a9a886654 100644
--- a/src/_styles/common/light.ts
+++ b/src/_styles/common/light.ts
@@ -140,13 +140,13 @@ const derived = {
   borderColor: 'rgb(224, 224, 230)',
 
   // close
-  closeColorHover: neutral(Number(base.alphaClose) * 0.8),
   closeColor: neutral(Number(base.alphaClose)),
-  closeColorPressed: scaleColor(neutral(base.alphaClose), { lightness: 1.25 }),
+  closeColorHover: neutral(Number(base.alphaClose) * 1.25),
+  closeColorPressed: neutral(Number(base.alphaClose) * 0.8),
   closeColorDisabled: neutral(base.alpha4),
   closeOpacity: base.alphaClose,
-  closeOpacityHover: String(roundAlpha(Number(base.alphaClose) * 0.8)),
-  closeOpacityPressed: String(roundAlpha(Number(base.alphaClose) * 1.25)),
+  closeOpacityHover: String(roundAlpha(Number(base.alphaClose) * 1.25)),
+  closeOpacityPressed: String(roundAlpha(Number(base.alphaClose) * 0.8)),
 
   // clear
   clearColor: neutral(base.alpha4),
diff --git a/src/drawer/demos/zhCN/dark-1-debug.demo.md b/src/drawer/demos/zhCN/dark-1-debug.demo.md
index 25b3743b3..55f39146f 100644
--- a/src/drawer/demos/zhCN/dark-1-debug.demo.md
+++ b/src/drawer/demos/zhCN/dark-1-debug.demo.md
@@ -145,8 +145,14 @@
 ```
 
 ```js
+import { useMessage } from 'naive-ui'
+
 export default {
-  inject: ['message'],
+  setup () {
+    return {
+      message: useMessage()
+    }
+  },
   data () {
     return {
       modalActive: false,
diff --git a/src/drawer/demos/zhCN/dark-3-debug.demo.md b/src/drawer/demos/zhCN/dark-3-debug.demo.md
index e42c103af..7e4c65a87 100644
--- a/src/drawer/demos/zhCN/dark-3-debug.demo.md
+++ b/src/drawer/demos/zhCN/dark-3-debug.demo.md
@@ -85,7 +85,6 @@ const data = Array.apply(null, { length: 46 }).map((_, index) => ({
 }))
 
 export default {
-  inject: ['message'],
   data () {
     return {
       modalActive: false,
@@ -97,11 +96,6 @@ export default {
     pagination () {
       return { pageSize: 10 }
     }
-  },
-  methods: {
-    sendMail (rowData) {
-      this.message.info('send mail to ' + rowData.name)
-    }
   }
 }
 ```
diff --git a/src/form/demos/enUS/change-debug.demo.md b/src/form/demos/enUS/change-debug.demo.md
index 369b2a610..14444b3aa 100644
--- a/src/form/demos/enUS/change-debug.demo.md
+++ b/src/form/demos/enUS/change-debug.demo.md
@@ -20,8 +20,14 @@
 ```
 
 ```js
+import { useMessage } from 'naive-ui'
+
 export default {
-  inject: ['message'],
+  setup () {
+    return {
+      message: useMessage()
+    }
+  },
   data () {
     return {
       show: true,
diff --git a/src/form/demos/enUS/required-mark-debug.demo.md b/src/form/demos/enUS/required-mark-debug.demo.md
index bca370eee..dedb73cea 100644
--- a/src/form/demos/enUS/required-mark-debug.demo.md
+++ b/src/form/demos/enUS/required-mark-debug.demo.md
@@ -46,8 +46,14 @@
 ```
 
 ```js
+import { useMessage } from 'naive-ui'
+
 export default {
-  inject: ['message'],
+  setup () {
+    return {
+      message: useMessage()
+    }
+  },
   data () {
     return {
       model: {
diff --git a/src/form/demos/zhCN/height-debug.demo.md b/src/form/demos/zhCN/height-debug.demo.md
index d5d811daf..4b57790e7 100644
--- a/src/form/demos/zhCN/height-debug.demo.md
+++ b/src/form/demos/zhCN/height-debug.demo.md
@@ -21,8 +21,14 @@ Buggy!
 ```
 
 ```js
+import { useMessage } from 'naive-ui'
+
 export default {
-  inject: ['message'],
+  setup () {
+    return {
+      message: useMessage()
+    }
+  },
   data () {
     return {
       size: 'medium',
diff --git a/src/form/demos/zhCN/validator-debug.demo.md b/src/form/demos/zhCN/validator-debug.demo.md
index ef8180f80..4b614c451 100644
--- a/src/form/demos/zhCN/validator-debug.demo.md
+++ b/src/form/demos/zhCN/validator-debug.demo.md
@@ -48,8 +48,14 @@
 ```
 
 ```js
+import { useMessage } from 'naive-ui'
+
 export default {
-  inject: ['message'],
+  setup () {
+    return {
+      message: useMessage()
+    }
+  },
   data () {
     return {
       formValue: {
diff --git a/src/icon/src/Icon.ts b/src/icon/src/Icon.ts
index 705340e26..268d9bb74 100644
--- a/src/icon/src/Icon.ts
+++ b/src/icon/src/Icon.ts
@@ -9,7 +9,7 @@ import style from './styles/index.cssr'
 export type Depth = 1 | 2 | 3 | 4 | 5 | '1' | '2' | '3' | '4' | '5' | undefined
 
 export default defineComponent({
-  __NAIVE_ICON__: true,
+  __ICON__: true,
   name: 'Icon',
   props: {
     ...(useTheme.props as ThemeProps<IconTheme>),
@@ -67,7 +67,7 @@ export default defineComponent({
   },
   render () {
     const { $parent, depth, cPrefix } = this
-    if ($parent?.$options.__NAIVE_ICON__) {
+    if ($parent?.$options.__ICON__) {
       warn('icon', "don't wrap `n-icon` inside `n-icon`")
     }
     return h(
diff --git a/src/input/demos/enUS/event.demo.md b/src/input/demos/enUS/event.demo.md
index f07a4d892..33f5d8245 100644
--- a/src/input/demos/enUS/event.demo.md
+++ b/src/input/demos/enUS/event.demo.md
@@ -23,24 +23,29 @@
 ```
 
 ```js
-export default {
-  inject: ['message'],
-  methods: {
-    handleFocus () {
-      this.message.info('[Event focus]')
-    },
-    handleBlur () {
-      this.message.info('[Event blur]')
-    },
-    handleChange (v) {
-      this.message.info('[Event change]' + v)
-    },
-    handleKeyUp (e) {
-      this.message.info('[Event keyup]')
-    },
-    handleInput (v) {
-      this.message.info('[Event input] ' + v)
+import { defineComponent } from 'vue'
+import { useMessage } from 'naive-ui'
+
+export default defineComponent({
+  setup () {
+    const message = useMessage()
+    return {
+      handleFocus (e) {
+        message.info('[Event focus]')
+      },
+      handleBlur (e) {
+        message.info('[Event blur]')
+      },
+      handleChange (v) {
+        message.info('[Event change]: ' + v)
+      },
+      handleKeyUp (e) {
+        message.info('[Event keyup]')
+      },
+      handleInput (v) {
+        message.info('[Event input]: ' + v)
+      }
     }
   }
-}
+})
 ```
diff --git a/src/input/demos/enUS/pair.demo.md b/src/input/demos/enUS/pair.demo.md
index f271c078c..31400648f 100644
--- a/src/input/demos/enUS/pair.demo.md
+++ b/src/input/demos/enUS/pair.demo.md
@@ -14,26 +14,27 @@
 ```
 
 ```js
-export default {
-  inject: ['message'],
-  data () {
+import { defineComponent } from 'vue'
+import { useMessage } from 'naive-ui'
+
+export default defineComponent({
+  setup () {
+    const message = useMessage()
     return {
-      placeholder: ['From', 'To']
-    }
-  },
-  methods: {
-    handleInputBlur () {
-      this.message.info('Pairwise Value:Blur')
-    },
-    handleInputFocus () {
-      this.message.info('Pairwise Value:Focus')
-    },
-    handleInputInput () {
-      this.message.info('Pairwise Value:Input')
-    },
-    handleInputChange () {
-      this.message.info('Pairwise Value:Change')
+      placeholder: ['From', 'To'],
+      handleInputBlur () {
+        message.info('Pairwise Value:Blur')
+      },
+      handleInputFocus () {
+        message.info('Pairwise Value:Focus')
+      },
+      handleInputInput () {
+        message.info('Pairwise Value:Input')
+      },
+      handleInputChange () {
+        message.info('Pairwise Value:Change')
+      }
     }
   }
-}
+})
 ```
diff --git a/src/input/demos/enUS/passively-activated.demo.md b/src/input/demos/enUS/passively-activated.demo.md
index eadad2b00..b4af085dc 100644
--- a/src/input/demos/enUS/passively-activated.demo.md
+++ b/src/input/demos/enUS/passively-activated.demo.md
@@ -34,24 +34,29 @@ If you want to activate input by pressing enter after focused, use `passively-ac
 ```
 
 ```js
-export default {
-  inject: ['message'],
-  methods: {
-    handleFocus (e) {
-      this.message.info('[Event focus]')
-    },
-    handleBlur (e) {
-      this.message.info('[Event blur]')
-    },
-    handleChange (v) {
-      this.message.info('[Event change]: ' + v)
-    },
-    handleKeyUp (e) {
-      this.message.info('[Event keyup]')
-    },
-    handleInput (v) {
-      this.message.info('[Event input]: ' + v)
+import { defineComponent } from 'vue'
+import { useMessage } from 'naive-ui'
+
+export default defineComponent({
+  setup () {
+    const message = useMessage()
+    return {
+      handleFocus (e) {
+        message.info('[Event focus]')
+      },
+      handleBlur (e) {
+        message.info('[Event blur]')
+      },
+      handleChange (v) {
+        message.info('[Event change]: ' + v)
+      },
+      handleKeyUp (e) {
+        message.info('[Event keyup]')
+      },
+      handleInput (v) {
+        message.info('[Event input]: ' + v)
+      }
     }
   }
-}
+})
 ```
diff --git a/src/input/demos/zhCN/event.demo.md b/src/input/demos/zhCN/event.demo.md
index 18a9cad63..d84cf2377 100644
--- a/src/input/demos/zhCN/event.demo.md
+++ b/src/input/demos/zhCN/event.demo.md
@@ -23,24 +23,29 @@
 ```
 
 ```js
-export default {
-  inject: ['message'],
-  methods: {
-    handleFocus () {
-      this.message.info('[Event focus]')
-    },
-    handleBlur () {
-      this.message.info('[Event blur]')
-    },
-    handleChange (v) {
-      this.message.info('[Event change]' + v)
-    },
-    handleKeyUp (e) {
-      this.message.info('[Event keyup]')
-    },
-    handleInput (v) {
-      this.message.info('[Event input] ' + v)
+import { defineComponent } from 'vue'
+import { useMessage } from 'naive-ui'
+
+export default defineComponent({
+  setup () {
+    const message = useMessage()
+    return {
+      handleFocus (e) {
+        message.info('[Event focus]')
+      },
+      handleBlur (e) {
+        message.info('[Event blur]')
+      },
+      handleChange (v) {
+        message.info('[Event change]: ' + v)
+      },
+      handleKeyUp (e) {
+        message.info('[Event keyup]')
+      },
+      handleInput (v) {
+        message.info('[Event input]: ' + v)
+      }
     }
   }
-}
+})
 ```
diff --git a/src/input/demos/zhCN/pair.demo.md b/src/input/demos/zhCN/pair.demo.md
index 6d225dfe4..a5748f57b 100644
--- a/src/input/demos/zhCN/pair.demo.md
+++ b/src/input/demos/zhCN/pair.demo.md
@@ -14,26 +14,27 @@
 ```
 
 ```js
-export default {
-  inject: ['message'],
-  data () {
+import { defineComponent } from 'vue'
+import { useMessage } from 'naive-ui'
+
+export default defineComponent({
+  setup () {
+    const message = useMessage()
     return {
-      placeholder: ['从', '到']
-    }
-  },
-  methods: {
-    handleInputBlur () {
-      this.message.info('输入成对值:Blur')
-    },
-    handleInputFocus () {
-      this.message.info('输入成对值:Focus')
-    },
-    handleInputInput () {
-      this.message.info('输入成对值:Input')
-    },
-    handleInputChange () {
-      this.message.info('输入成对值:Change')
+      placeholder: ['从', '到'],
+      handleInputBlur () {
+        message.info('输入成对值:Blur')
+      },
+      handleInputFocus () {
+        message.info('输入成对值:Focus')
+      },
+      handleInputInput () {
+        message.info('输入成对值:Input')
+      },
+      handleInputChange () {
+        message.info('输入成对值:Change')
+      }
     }
   }
-}
+})
 ```
diff --git a/src/input/demos/zhCN/passively-activated.demo.md b/src/input/demos/zhCN/passively-activated.demo.md
index 94ebc4359..76d9ea111 100644
--- a/src/input/demos/zhCN/passively-activated.demo.md
+++ b/src/input/demos/zhCN/passively-activated.demo.md
@@ -34,24 +34,29 @@
 ```
 
 ```js
-export default {
-  inject: ['message'],
-  methods: {
-    handleFocus (e) {
-      this.message.info('[Event focus]')
-    },
-    handleBlur (e) {
-      this.message.info('[Event blur]')
-    },
-    handleChange (v) {
-      this.message.info('[Event change]: ' + v)
-    },
-    handleKeyUp (e) {
-      this.message.info('[Event keyup]')
-    },
-    handleInput (v) {
-      this.message.info('[Event input]: ' + v)
+import { defineComponent } from 'vue'
+import { useMessage } from 'naive-ui'
+
+export default defineComponent({
+  setup () {
+    const message = useMessage()
+    return {
+      handleFocus (e) {
+        message.info('[Event focus]')
+      },
+      handleBlur (e) {
+        message.info('[Event blur]')
+      },
+      handleChange (v) {
+        message.info('[Event change]: ' + v)
+      },
+      handleKeyUp (e) {
+        message.info('[Event keyup]')
+      },
+      handleInput (v) {
+        message.info('[Event input]: ' + v)
+      }
     }
   }
-}
+})
 ```
diff --git a/src/log/demos/enUS/event.demo.md b/src/log/demos/enUS/event.demo.md
index 95e9c7139..7341a80bb 100644
--- a/src/log/demos/enUS/event.demo.md
+++ b/src/log/demos/enUS/event.demo.md
@@ -14,6 +14,9 @@ Log has `require-more`, `reach-top` and `reach-bottom` event. Note that even if
 ```
 
 ```js
+import { defineComponent, ref } from 'vue'
+import { useMessage } from 'naive-ui'
+
 function log () {
   const l = []
   for (let i = 0; i < 10; ++i) {
@@ -22,37 +25,37 @@ function log () {
   return l.join('\n') + '\n'
 }
 
-export default {
-  inject: ['message'],
-  data () {
+export default defineComponent({
+  setup () {
+    const message = useMessage()
+    const loadingRef = ref(false)
+    const logRef = ref(log())
     return {
       loading: false,
-      log: log()
-    }
-  },
-  methods: {
-    clear () {
-      this.log = ''
-    },
-    handleRequireMore (from) {
-      this.message.info('Require More from ' + from)
-      if (this.loading) return
-      this.loading = true
-      setTimeout(() => {
-        if (from === 'top') {
-          this.log = log() + this.log
-        } else if (from === 'bottom') {
-          this.log = this.log + log()
-        }
-        this.loading = false
-      }, 1000)
-    },
-    handleReachTop () {
-      this.message.info('Reach Top')
-    },
-    handleReachBottom () {
-      this.message.info('Reach Bottom')
+      log: log(),
+      clear () {
+        logRef.value = ''
+      },
+      handleRequireMore (from) {
+        message.info('Require More from ' + from)
+        if (loadingRef.value) return
+        loadingRef.value = true
+        setTimeout(() => {
+          if (from === 'top') {
+            logRef.value = log() + logRef.value
+          } else if (from === 'bottom') {
+            logRef.value = logRef.value + log()
+          }
+          loadingRef.value = false
+        }, 1000)
+      },
+      handleReachTop () {
+        message.info('Reach Top')
+      },
+      handleReachBottom () {
+        message.info('Reach Bottom')
+      }
     }
   }
-}
+})
 ```
diff --git a/src/log/demos/enUS/scroll.demo.md b/src/log/demos/enUS/scroll.demo.md
index 98dd2ae51..31361b96e 100644
--- a/src/log/demos/enUS/scroll.demo.md
+++ b/src/log/demos/enUS/scroll.demo.md
@@ -19,7 +19,7 @@ You can easily make log scroll to top or bottom. Also you can make the scroll ac
     >
   </n-button-group>
   <n-log
-    ref="log"
+    ref="logInstRef"
     :log="log"
     @require-more="handleRequireMore"
     @reach-top="handleReachTop"
@@ -31,6 +31,9 @@ You can easily make log scroll to top or bottom. Also you can make the scroll ac
 ```
 
 ```js
+import { defineComponent, ref } from 'vue'
+import { useMessage } from 'naive-ui'
+
 function log () {
   const l = []
   for (let i = 0; i < 10; ++i) {
@@ -39,40 +42,42 @@ function log () {
   return l.join('\n') + '\n'
 }
 
-export default {
-  inject: ['message'],
-  data () {
+export default defineComponent({
+  setup () {
+    const message = useMessage()
+    const loadingRef = ref(false)
+    const logRef = ref(log())
+    const logInstRef = ref(null)
     return {
+      logInstRef,
       loading: false,
-      log: log()
-    }
-  },
-  methods: {
-    clear () {
-      this.log = ''
-    },
-    handleRequireMore (from) {
-      this.message.info('Require More from ' + from)
-      if (this.loading) return
-      this.loading = true
-      setTimeout(() => {
-        if (from === 'top') {
-          this.log = log() + this.log
-        } else if (from === 'bottom') {
-          this.log = this.log + log()
-        }
-        this.loading = false
-      }, 1000)
-    },
-    handleReachTop () {
-      this.message.info('Reach Top')
-    },
-    handleReachBottom () {
-      this.message.info('Reach Bottom')
-    },
-    scrollTo (...args) {
-      this.$refs.log.scrollTo(...args)
+      log: log(),
+      clear () {
+        logRef.value = ''
+      },
+      handleRequireMore (from) {
+        message.info('Require More from ' + from)
+        if (loadingRef.value) return
+        loadingRef.value = true
+        setTimeout(() => {
+          if (from === 'top') {
+            logRef.value = log() + logRef.value
+          } else if (from === 'bottom') {
+            logRef.value = logRef.value + log()
+          }
+          loadingRef.value = false
+        }, 1000)
+      },
+      handleReachTop () {
+        message.info('Reach Top')
+      },
+      handleReachBottom () {
+        message.info('Reach Bottom')
+      },
+      scrollTo (...args) {
+        logInstRef.value.scrollTo(...args)
+      }
     }
   }
-}
+})
 ```
diff --git a/src/log/demos/zhCN/event.demo.md b/src/log/demos/zhCN/event.demo.md
index 474e55c50..58f78b843 100644
--- a/src/log/demos/zhCN/event.demo.md
+++ b/src/log/demos/zhCN/event.demo.md
@@ -14,6 +14,9 @@ Log 有 `require-more`、`reach-top` 和 `reach-bottom` 事件。需要注意的
 ```
 
 ```js
+import { defineComponent, ref } from 'vue'
+import { useMessage } from 'naive-ui'
+
 function log () {
   const l = []
   for (let i = 0; i < 10; ++i) {
@@ -22,37 +25,37 @@ function log () {
   return l.join('\n') + '\n'
 }
 
-export default {
-  inject: ['message'],
-  data () {
+export default defineComponent({
+  setup () {
+    const message = useMessage()
+    const loadingRef = ref(false)
+    const logRef = ref(log())
     return {
       loading: false,
-      log: log()
-    }
-  },
-  methods: {
-    clear () {
-      this.log = ''
-    },
-    handleRequireMore (from) {
-      this.message.info('Require More from ' + from)
-      if (this.loading) return
-      this.loading = true
-      setTimeout(() => {
-        if (from === 'top') {
-          this.log = log() + this.log
-        } else if (from === 'bottom') {
-          this.log = this.log + log()
-        }
-        this.loading = false
-      }, 1000)
-    },
-    handleReachTop () {
-      this.message.info('Reach Top')
-    },
-    handleReachBottom () {
-      this.message.info('Reach Bottom')
+      log: log(),
+      clear () {
+        logRef.value = ''
+      },
+      handleRequireMore (from) {
+        message.info('Require More from ' + from)
+        if (loadingRef.value) return
+        loadingRef.value = true
+        setTimeout(() => {
+          if (from === 'top') {
+            logRef.value = log() + logRef.value
+          } else if (from === 'bottom') {
+            logRef.value = logRef.value + log()
+          }
+          loadingRef.value = false
+        }, 1000)
+      },
+      handleReachTop () {
+        message.info('Reach Top')
+      },
+      handleReachBottom () {
+        message.info('Reach Bottom')
+      }
     }
   }
-}
+})
 ```
diff --git a/src/log/demos/zhCN/scroll.demo.md b/src/log/demos/zhCN/scroll.demo.md
index 0ed311408..3ed7bb35f 100644
--- a/src/log/demos/zhCN/scroll.demo.md
+++ b/src/log/demos/zhCN/scroll.demo.md
@@ -19,7 +19,7 @@
     >
   </n-button-group>
   <n-log
-    ref="log"
+    ref="logInstRef"
     :log="log"
     @require-more="handleRequireMore"
     @reach-top="handleReachTop"
@@ -31,6 +31,9 @@
 ```
 
 ```js
+import { defineComponent, ref } from 'vue'
+import { useMessage } from 'naive-ui'
+
 function log () {
   const l = []
   for (let i = 0; i < 10; ++i) {
@@ -39,40 +42,42 @@ function log () {
   return l.join('\n') + '\n'
 }
 
-export default {
-  inject: ['message'],
-  data () {
+export default defineComponent({
+  setup () {
+    const message = useMessage()
+    const loadingRef = ref(false)
+    const logRef = ref(log())
+    const logInstRef = ref(null)
     return {
+      logInstRef,
       loading: false,
-      log: log()
-    }
-  },
-  methods: {
-    clear () {
-      this.log = ''
-    },
-    handleRequireMore (from) {
-      this.message.info('Require More from ' + from)
-      if (this.loading) return
-      this.loading = true
-      setTimeout(() => {
-        if (from === 'top') {
-          this.log = log() + this.log
-        } else if (from === 'bottom') {
-          this.log = this.log + log()
-        }
-        this.loading = false
-      }, 1000)
-    },
-    handleReachTop () {
-      this.message.info('Reach Top')
-    },
-    handleReachBottom () {
-      this.message.info('Reach Bottom')
-    },
-    scrollTo (...args) {
-      this.$refs.log.scrollTo(...args)
+      log: log(),
+      clear () {
+        logRef.value = ''
+      },
+      handleRequireMore (from) {
+        message.info('Require More from ' + from)
+        if (loadingRef.value) return
+        loadingRef.value = true
+        setTimeout(() => {
+          if (from === 'top') {
+            logRef.value = log() + logRef.value
+          } else if (from === 'bottom') {
+            logRef.value = logRef.value + log()
+          }
+          loadingRef.value = false
+        }, 1000)
+      },
+      handleReachTop () {
+        message.info('Reach Top')
+      },
+      handleReachBottom () {
+        message.info('Reach Bottom')
+      },
+      scrollTo (...args) {
+        logInstRef.value.scrollTo(...args)
+      }
     }
   }
-}
+})
 ```
diff --git a/src/message/demos/enUS/icon.demo.md b/src/message/demos/enUS/icon.demo.md
index 5823b8bed..9db79b8a8 100644
--- a/src/message/demos/enUS/icon.demo.md
+++ b/src/message/demos/enUS/icon.demo.md
@@ -15,7 +15,7 @@ export default {
     return {
       createMessage () {
         message.warning("I never needed anybody's help in any way", {
-          icon: () => h(NIcon, { default: () => h(MdHourglass) })
+          icon: () => h(NIcon, null, { default: () => h(MdHourglass) })
         })
       }
     }
diff --git a/src/message/demos/zhCN/icon.demo.md b/src/message/demos/zhCN/icon.demo.md
index d4334df50..9fc1c8ef0 100644
--- a/src/message/demos/zhCN/icon.demo.md
+++ b/src/message/demos/zhCN/icon.demo.md
@@ -15,7 +15,7 @@ export default {
     return {
       createMessage () {
         message.warning("I never needed anybody's help in any way", {
-          icon: () => h(NIcon, { default: () => h(MdHourglass) })
+          icon: () => h(NIcon, null, { default: () => h(MdHourglass) })
         })
       }
     }
diff --git a/src/message/index.ts b/src/message/index.ts
index c69b1cff1..6435013fd 100644
--- a/src/message/index.ts
+++ b/src/message/index.ts
@@ -1,7 +1,8 @@
 export { default as NMessageProvider } from './src/MessageProvider'
 export { useMessage } from './src/use-message'
 export type {
+  MessageProviderInst,
+  MessageProviderProps,
   MessageOptions,
-  MessageApiInjection,
   MessageReactive
 } from './src/MessageProvider'
diff --git a/src/message/src/Message.ts b/src/message/src/Message.tsx
similarity index 58%
rename from src/message/src/Message.ts
rename to src/message/src/Message.tsx
index e9f4476fa..59a554f9a 100644
--- a/src/message/src/Message.ts
+++ b/src/message/src/Message.tsx
@@ -1,4 +1,11 @@
-import { computed, h, defineComponent, inject, VNodeChild } from 'vue'
+import {
+  computed,
+  h,
+  defineComponent,
+  inject,
+  VNodeChild,
+  CSSProperties
+} from 'vue'
 import {
   InfoIcon,
   SuccessIcon,
@@ -12,35 +19,38 @@ import {
   NBaseClose
 } from '../../_internal'
 import { render, createKey } from '../../_utils'
-import { ThemePropsReactive, useTheme } from '../../_mixins'
-import { messageLight, MessageTheme } from '../styles'
+import { useTheme } from '../../_mixins'
+import { messageLight } from '../styles'
 import { messageProps, MessageType } from './message-props'
+import { messageProviderInjectionKey } from './MessageProvider'
 import style from './styles/index.cssr'
 
 const iconMap = {
-  info: InfoIcon,
-  success: SuccessIcon,
-  warning: WarningIcon,
-  error: ErrorIcon,
-  loading: NBaseLoading
+  info: <InfoIcon />,
+  success: <SuccessIcon />,
+  warning: <WarningIcon />,
+  error: <ErrorIcon />
 }
 
 export default defineComponent({
   name: 'Message',
   props: messageProps,
   setup (props) {
-    // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-    const themeProps = inject<ThemePropsReactive<MessageTheme>>(
-      'NMessageProvider'
-    )!
+    const {
+      props: messageProviderProps,
+      cPrefixRef
+      // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+    } = inject(messageProviderInjectionKey)!
     const themeRef = useTheme(
       'Message',
       'Message',
       style,
       messageLight,
-      themeProps
+      messageProviderProps,
+      cPrefixRef
     )
     return {
+      cPrefix: cPrefixRef,
       handleClose () {
         props.onClose?.()
       },
@@ -100,74 +110,67 @@ export default defineComponent({
     }
   },
   render () {
-    const { icon, type, closable, content, handleClose, cssVars } = this
-    return h(
-      'div',
-      {
-        class: 'n-message-wrapper',
-        style: cssVars
-      },
-      [
-        h(
-          'div',
-          {
-            class: 'n-message'
-          },
-          [
-            h(
-              'div',
-              {
-                class: [
-                  'n-message__icon',
-                  `n-message__icon n-message__icon--${type}-type`
-                ]
-              },
-              [
-                h(NIconSwitchTransition, null, {
-                  default: () => [createIconVNode(icon, type)]
-                })
-              ]
-            ),
-            h(
-              'div',
-              {
-                class: 'n-message__content'
-              },
-              [
-                h(render, {
-                  render: content
-                })
-              ]
-            ),
-            closable
-              ? h(NBaseClose, {
-                class: 'n-message__close',
-                onClick: handleClose
-              })
-              : null
-          ]
-        )
-      ]
+    const {
+      icon,
+      type,
+      closable,
+      content,
+      cPrefix,
+      cssVars,
+      handleClose
+    } = this
+    return (
+      <div
+        class={`${cPrefix}-message-wrapper`}
+        style={cssVars as CSSProperties}
+      >
+        <div class={`${cPrefix}-message`}>
+          <div
+            class={`${cPrefix}-message__icon ${cPrefix}-message__icon--${type}-type`}
+          >
+            <NIconSwitchTransition>
+              {{
+                default: () => [createIconVNode(icon, type, cPrefix)]
+              }}
+            </NIconSwitchTransition>
+          </div>
+          <div class={`${cPrefix}-message__content`}>
+            {h(render, {
+              render: content
+            })}
+          </div>
+          {closable ? (
+            <NBaseClose
+              clsPrefix={cPrefix}
+              class={`${cPrefix}-message__close`}
+              onClick={handleClose}
+            />
+          ) : null}
+        </div>
+      </div>
     )
   }
 })
 
 function createIconVNode (
   icon: undefined | (() => VNodeChild),
-  type: MessageType
+  type: MessageType,
+  clsPrefix: string
 ): VNodeChild {
   if (typeof icon === 'function') {
     return icon()
   } else {
-    return h(
-      NBaseIcon,
-      {
-        key: type
-      },
-      {
-        default: () =>
-          h(iconMap[type], type === 'loading' ? { scale: 0.85 } : undefined)
-      }
+    return (
+      <NBaseIcon clsPrefix={clsPrefix} key={type}>
+        {{
+          default: () =>
+            type === 'loading' ? (
+              <NBaseLoading clsPrefix={clsPrefix} scale={0.85} />
+            ) : (
+              iconMap[type]
+            )
+        }}
+      </NBaseIcon>
     )
   }
 }
diff --git a/src/message/src/MessageEnvironment.ts b/src/message/src/MessageEnvironment.tsx
similarity index 68%
rename from src/message/src/MessageEnvironment.ts
rename to src/message/src/MessageEnvironment.tsx
index aa722563c..690abc5a0 100644
--- a/src/message/src/MessageEnvironment.ts
+++ b/src/message/src/MessageEnvironment.tsx
@@ -11,28 +11,16 @@ export default defineComponent({
       type: Number,
       default: 3000
     },
-    onAfterLeave: {
-      type: Function,
-      default: undefined
-    },
+    onAfterLeave: Function,
     internalKey: {
       type: String,
       required: true
     },
     // private
-    onInternalAfterLeave: {
-      type: Function as PropType<(key: string) => void>,
-      default: undefined
-    },
+    onInternalAfterLeave: Function as PropType<(key: string) => void>,
     // deprecated
-    onHide: {
-      type: Function,
-      default: undefined
-    },
-    onAfterHide: {
-      type: Function,
-      default: undefined
-    }
+    onHide: Function,
+    onAfterHide: Function
   },
   setup (props) {
     const timerIdRef = ref<number | null>(null)
@@ -83,25 +71,22 @@ export default defineComponent({
     }
   },
   render () {
-    return h(
-      NFadeInExpandTransition,
-      {
-        appear: true,
-        onAfterLeave: this.handleAfterLeave
-      },
-      {
-        default: () => [
-          this.show
-            ? h(NMessage, {
-              content: this.content,
-              type: this.type,
-              icon: this.icon,
-              closable: this.closable,
-              onClose: this.handleClose
-            })
-            : null
-        ]
-      }
+    return (
+      <NFadeInExpandTransition appear onAfterLeave={this.handleAfterLeave}>
+        {{
+          default: () => [
+            this.show ? (
+              <NMessage
+                content={this.content}
+                type={this.type}
+                icon={this.icon}
+                closable={this.closable}
+                onClose={this.handleClose}
+              />
+            ) : null
+          ]
+        }}
+      </NFadeInExpandTransition>
     )
   }
 })
diff --git a/src/message/src/MessageProvider.ts b/src/message/src/MessageProvider.tsx
similarity index 57%
rename from src/message/src/MessageProvider.ts
rename to src/message/src/MessageProvider.tsx
index 959a8d334..6bf3782c0 100644
--- a/src/message/src/MessageProvider.ts
+++ b/src/message/src/MessageProvider.tsx
@@ -6,11 +6,15 @@ import {
   Teleport,
   defineComponent,
   provide,
-  VNodeChild
+  VNodeChild,
+  InjectionKey,
+  ExtractPropTypes,
+  renderSlot,
+  Ref
 } from 'vue'
 import { createId } from 'seemly'
-import { omit } from '../../_utils'
-import { ThemePropsReactive, useTheme } from '../../_mixins'
+import { ExtractPublicPropTypes, omit } from '../../_utils'
+import { useConfig, useTheme } from '../../_mixins'
 import type { ThemeProps } from '../../_mixins'
 import MessageEnvironment from './MessageEnvironment'
 import { MessageTheme } from '../styles'
@@ -30,6 +34,10 @@ export interface MessageApiInjection {
   loading: (content: string, options: MessageOptions) => MessageReactive
 }
 
+export const messageApiInjectionKey: InjectionKey<MessageApiInjection> = Symbol(
+  'messageApi'
+)
+
 export interface MessageReactive {
   content?: string
   duration?: number
@@ -48,16 +56,30 @@ interface PrivateMessageRef extends MessageReactive {
   hide: () => void
 }
 
+export type MessageProviderInst = MessageApiInjection
+
+const messageProps = {
+  ...(useTheme.props as ThemeProps<MessageTheme>),
+  to: {
+    type: [String, Object],
+    default: undefined
+  }
+}
+
+export type MessageProviderProps = ExtractPublicPropTypes<typeof messageProps>
+
+type MessageProviderSetupProps = ExtractPropTypes<typeof messageProps>
+
+export const messageProviderInjectionKey: InjectionKey<{
+  props: MessageProviderSetupProps
+  cPrefixRef: Ref<string>
+}> = Symbol('messageProvider')
+
 export default defineComponent({
   name: 'MessageProvider',
-  props: {
-    ...(useTheme.props as ThemeProps<MessageTheme>),
-    to: {
-      type: [String, Object],
-      default: undefined
-    }
-  },
+  props: messageProps,
   setup (props) {
+    const { mergedClsPrefix } = useConfig(props)
     const messageListRef = ref<PrivateMessageReactive[]>([])
     const messageRefs = ref<{ [key: string]: PrivateMessageRef }>({})
     const api: MessageApiInjection = {
@@ -77,8 +99,8 @@ export default defineComponent({
         return create(content, { ...options, type: 'loading' })
       }
     }
-    provide<ThemePropsReactive<MessageTheme>>('NMessageProvider', props)
-    provide<MessageApiInjection>('message', api)
+    provide(messageProviderInjectionKey, { props, cPrefixRef: mergedClsPrefix })
+    provide(messageApiInjectionKey, api)
     function create (content: string, options = {}): MessageReactive {
       const key = createId()
       const messageReactive = reactive({
@@ -86,7 +108,7 @@ export default defineComponent({
         content,
         key,
         destroy: () => {
-          messageRefs.value[`n-message-${key}`].hide()
+          messageRefs.value[key].hide()
         }
       })
       messageListRef.value.push(messageReactive)
@@ -99,42 +121,41 @@ export default defineComponent({
       )
     }
     return {
+      cPrefix: mergedClsPrefix,
       messageRefs,
       messageList: messageListRef,
-      handleAfterLeave
+      handleAfterLeave,
+      ...api
     }
   },
   render () {
-    const { default: defaultSlot } = this.$slots
-    return h(Fragment, null, [
-      this.messageList.length
-        ? h(
-          Teleport,
-          {
-            to: this.to ?? 'body'
-          },
-          [
-            h(
-              'div',
-              {
-                class: 'n-message-container',
-                key: 'n-message-container'
-              },
-              this.messageList.map((message) => {
-                return h(MessageEnvironment, {
-                  ref: ((inst: PrivateMessageRef) => {
-                    this.messageRefs[`n-message-${message.key}`] = inst
-                  }) as () => void,
-                  internalKey: message.key,
-                  onInternalAfterLeave: this.handleAfterLeave,
-                  ...omit(message, ['destroy'], undefined)
-                })
-              })
-            )
-          ]
-        )
-        : null,
-      defaultSlot?.()
-    ])
+    return (
+      <>
+        {renderSlot(this.$slots, 'default')}
+        {this.messageList.length ? (
+          <Teleport to={this.to ?? 'body'}>
+            <div
+              class={`${this.cPrefix}-message-container`}
+              key="message-container"
+            >
+              {this.messageList.map((message) => {
+                return (
+                  <MessageEnvironment
+                    ref={
+                      ((inst: PrivateMessageRef) => {
+                        this.messageRefs[message.key] = inst
+                      }) as () => void
+                    }
+                    internalKey={message.key}
+                    onInternalAfterLeave={this.handleAfterLeave}
+                    {...omit(message, ['destroy'], undefined)}
+                  />
+                )
+              })}
+            </div>
+          </Teleport>
+        ) : null}
+      </>
+    )
   }
 })
diff --git a/src/message/src/message-props.ts b/src/message/src/message-props.ts
index a5e945607..3f88a8323 100644
--- a/src/message/src/message-props.ts
+++ b/src/message/src/message-props.ts
@@ -8,12 +8,9 @@ export const messageProps = {
     type: String as PropType<MessageType>,
     default: 'info'
   },
-  content: {
-    type: [String, Number, Boolean, Function] as PropType<
-    string | number | boolean | (() => VNodeChild)
-    >,
-    default: undefined
-  },
+  content: [String, Number, Boolean, Function] as PropType<
+  string | number | boolean | (() => VNodeChild)
+  >,
   closable: {
     type: Boolean,
     default: false
diff --git a/src/message/src/styles/index.cssr.ts b/src/message/src/styles/index.cssr.ts
index 1b9d3b998..3c9e11436 100644
--- a/src/message/src/styles/index.cssr.ts
+++ b/src/message/src/styles/index.cssr.ts
@@ -82,13 +82,13 @@ export default c([
           `)
         ])
       ),
-      c('> *', {
-        position: 'absolute',
-        left: 0,
-        top: 0,
-        right: 0,
-        bottom: 0
-      },
+      c('> *', `
+        position: absolute;
+        left: 0;
+        top: 0;
+        right: 0;
+        bottom: 0;
+      `,
       [iconSwitchTransition()])
     ]),
     cE('close', `
@@ -96,7 +96,14 @@ export default c([
       margin: var(--close-margin);
       transition: color .3s var(--bezier);
       flex-shrink: 0;
-    `)
+    `, [
+      c('&:hover', `
+        color: var(--close-color-hover);
+      `),
+      c('&:active', `
+        color: var(--close-color-pressed);
+      `)
+    ])
   ]),
   cB('message-container', `
     z-index: 6000;
diff --git a/src/message/src/use-message.ts b/src/message/src/use-message.ts
index 84cf42eec..e4aa2ed29 100644
--- a/src/message/src/use-message.ts
+++ b/src/message/src/use-message.ts
@@ -1,9 +1,12 @@
 import { inject } from 'vue'
 import { throwError } from '../../_utils'
+import { messageApiInjectionKey } from './MessageProvider'
 import type { MessageApiInjection } from './MessageProvider'
 
 export function useMessage (): MessageApiInjection {
-  const api = inject<MessageApiInjection>('message')
-  if (api === undefined) { throwError('use-message', 'No out <n-message-provider /> founded.') }
+  const api = inject(messageApiInjectionKey, null)
+  if (api === null) {
+    throwError('use-message', 'No outer <n-message-provider /> founded.')
+  }
   return api
 }
diff --git a/src/modal/demos/zhCN/dark-1-debug.demo.md b/src/modal/demos/zhCN/dark-1-debug.demo.md
index 3c73c3a59..efbe1e1b0 100644
--- a/src/modal/demos/zhCN/dark-1-debug.demo.md
+++ b/src/modal/demos/zhCN/dark-1-debug.demo.md
@@ -150,8 +150,14 @@
 ```
 
 ```js
+import { useMessage } from 'naive-ui'
+
 export default {
-  inject: ['message'],
+  setup () {
+    return {
+      message: useMessage()
+    }
+  },
   data () {
     return {
       showModal: false,
diff --git a/src/modal/demos/zhCN/dark-3-debug.demo.md b/src/modal/demos/zhCN/dark-3-debug.demo.md
index a5f4238ca..56799a74a 100644
--- a/src/modal/demos/zhCN/dark-3-debug.demo.md
+++ b/src/modal/demos/zhCN/dark-3-debug.demo.md
@@ -98,7 +98,6 @@ const data = Array.apply(null, { length: 46 }).map((_, index) => ({
 }))
 
 export default {
-  inject: ['message'],
   data () {
     return {
       showModal: false,
@@ -110,11 +109,6 @@ export default {
     pagination () {
       return { pageSize: 10 }
     }
-  },
-  methods: {
-    sendMail (rowData) {
-      this.message.info('send mail to ' + rowData.name)
-    }
   }
 }
 ```
diff --git a/src/modal/demos/zhCN/dark-6-debug.demo.md b/src/modal/demos/zhCN/dark-6-debug.demo.md
index 562bd28a3..5dd7b8836 100644
--- a/src/modal/demos/zhCN/dark-6-debug.demo.md
+++ b/src/modal/demos/zhCN/dark-6-debug.demo.md
@@ -151,8 +151,14 @@
 ```
 
 ```js
+import { useMessage } from 'naive-ui'
+
 export default {
-  inject: ['message'],
+  setup () {
+    return {
+      message: useMessage()
+    }
+  },
   data () {
     return {
       showModal: false,
diff --git a/src/modal/demos/zhCN/dark-9-debug.demo.md b/src/modal/demos/zhCN/dark-9-debug.demo.md
index 53f713212..a1ce1b9cd 100644
--- a/src/modal/demos/zhCN/dark-9-debug.demo.md
+++ b/src/modal/demos/zhCN/dark-9-debug.demo.md
@@ -95,7 +95,6 @@ const data = Array.apply(null, { length: 46 }).map((_, index) => ({
 }))
 
 export default {
-  inject: ['message'],
   data () {
     return {
       showModal: false,
@@ -107,11 +106,6 @@ export default {
     pagination () {
       return { pageSize: 10 }
     }
-  },
-  methods: {
-    sendMail (rowData) {
-      this.message.info('send mail to ' + rowData.name)
-    }
   }
 }
 ```
diff --git a/src/modal/demos/zhCN/drawer-debug.demo.md b/src/modal/demos/zhCN/drawer-debug.demo.md
index d6400ed0d..46eafe25d 100644
--- a/src/modal/demos/zhCN/drawer-debug.demo.md
+++ b/src/modal/demos/zhCN/drawer-debug.demo.md
@@ -163,8 +163,14 @@
 ```
 
 ```js
+import { useMessage } from 'naive-ui'
+
 export default {
-  inject: ['message'],
+  setup () {
+    return {
+      message: useMessage()
+    }
+  },
   data () {
     return {
       drawerActive: false,
diff --git a/src/tabs/demos/enUS/card.demo.md b/src/tabs/demos/enUS/card.demo.md
index 97193a73e..97ed5fe8b 100644
--- a/src/tabs/demos/enUS/card.demo.md
+++ b/src/tabs/demos/enUS/card.demo.md
@@ -27,26 +27,31 @@ A example to use with card. (demo is the card)
 ```
 
 ```js
-export default {
-  inject: ['message'],
-  data () {
-    return {
-      panels: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
-      name: '1',
-      tabNavScrollable: false
+import { defineComponent, ref } from 'vue'
+import { useMessage } from 'naive-ui'
+
+export default defineComponent({
+  setup () {
+    const message = useMessage()
+    const tabNavScrollableRef = ref(false)
+    const panelsRef = ref([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15])
+    function handleScrollableChange (value) {
+      tabNavScrollableRef.value = value
     }
-  },
-  methods: {
-    handleScrollableChange (value) {
-      this.tabNavScrollable = value
-    },
-    handleClose (name) {
-      this.message.info('Close ' + name)
-      const index = this.panels.findIndex((v) => name === v.toString())
+    function handleClose (name) {
+      message.info('Close ' + name)
+      const index = panelsRef.value.findIndex((v) => name === v.toString())
       if (~index) {
-        this.panels.splice(index, 1)
+        panelsRef.value.splice(index, 1)
       }
     }
+    return {
+      panels: panelsRef,
+      name: ref('1'),
+      tabNavScrollable: tabNavScrollableRef,
+      handleScrollableChange,
+      handleClose
+    }
   }
-}
+})
 ```
diff --git a/src/tabs/demos/zhCN/card.demo.md b/src/tabs/demos/zhCN/card.demo.md
index 2210e5887..2b9cc7a98 100644
--- a/src/tabs/demos/zhCN/card.demo.md
+++ b/src/tabs/demos/zhCN/card.demo.md
@@ -27,26 +27,31 @@
 ```
 
 ```js
-export default {
-  inject: ['message'],
-  data () {
-    return {
-      panels: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
-      name: '1',
-      tabNavScrollable: false
+import { defineComponent, ref } from 'vue'
+import { useMessage } from 'naive-ui'
+
+export default defineComponent({
+  setup () {
+    const message = useMessage()
+    const tabNavScrollableRef = ref(false)
+    const panelsRef = ref([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15])
+    function handleScrollableChange (value) {
+      tabNavScrollableRef.value = value
     }
-  },
-  methods: {
-    handleScrollableChange (value) {
-      this.tabNavScrollable = value
-    },
-    handleClose (name) {
-      this.message.info('Close ' + name)
-      const index = this.panels.findIndex((v) => name === v.toString())
+    function handleClose (name) {
+      message.info('Close ' + name)
+      const index = panelsRef.value.findIndex((v) => name === v.toString())
       if (~index) {
-        this.panels.splice(index, 1)
+        panelsRef.value.splice(index, 1)
       }
     }
+    return {
+      panels: panelsRef,
+      name: ref('1'),
+      tabNavScrollable: tabNavScrollableRef,
+      handleScrollableChange,
+      handleClose
+    }
   }
-}
+})
 ```