feat(transfer): there is still some bugs

This commit is contained in:
07akioni 2019-09-03 19:18:16 +08:00
parent 3021ec8fa5
commit 97d16c86c2
15 changed files with 747 additions and 61 deletions

View File

@ -114,15 +114,16 @@ Vue.use(naiveUi)
v0.3 cascader
v0.4 refactor popover
v0.5 finish all planned components
v0.6 refactor form component
v0.7 refactor table component
v0.8 fulfill props for all components
v0.9 split icons for components
v0.10 refactor css
v0.11 import on demand
v0.12 i18n
v0.13 unit test
v0.14 light theme
v0.15 document formation
v0.16 code clean
v0.17 refactor document page
v0.6 add keyboard event on planned components
v0.7 refactor form component
v0.8 refactor table component
v0.9 fulfill props for all components
v0.10 split icons for components
v0.11 refactor css
v0.12 import on demand
v0.13 i18n
v0.14 unit test
v0.15 light theme
v0.16 refactor using proper html tags
v0.17 document formation
v0.18 refactor document page

View File

@ -0,0 +1,32 @@
<template>
<div
ref="doc"
class="n-doc"
>
<div class="n-doc-header">
<n-gradient-text :font-size="20">
scaffold
</n-gradient-text>
</div>
<div class="n-doc-body">
<scaffold />
</div>
</div>
</template>
<script>
import scaffold from './scaffold.demo.vue'
export default {
components: {
scaffold
},
data () {
return {
}
},
methods: {
}
}
</script>

View File

@ -0,0 +1,67 @@
<template>
<div class="n-doc-section">
<div class="n-doc-section__header">
Scaffold
</div>
<div
class="n-doc-section__view"
style="flex-wrap: nowrap;"
>
<!--EXAMPLE_START-->
<n-transfer
ref="transfer"
v-model="value"
:options="options"
/>
<!--EXAMPLE_END-->
</div>
<div class="n-doc-section__inspect">
<n-button @click="regenOptions">
Regen Options
</n-button>
<n-button @click="regenValues">
Regen Values
</n-button>
</div>
<pre class="n-doc-section__inspect">{{ JSON.stringify(value) }}</pre>
<pre class="n-doc-section__inspect">{{ $refs.transfer ? $refs.transfer._data : null }}</pre>
<n-doc-source-block>
<!--SOURCE-->
</n-doc-source-block>
</div>
</template>
<script>
let prefix = null
function genOptions () {
prefix = Math.random().toString(36).slice(2, 5)
return Array.apply(null, { length: 20 }).map((v, i) => ({
label: prefix + 'Option' + i,
value: prefix + i
}))
}
function genValues () {
return Array.apply(null, { length: 5 }).map((v, i) => prefix + i)
}
export default {
data () {
return {
options: genOptions(),
value: genValues()
}
},
mounted () {
},
methods: {
regenOptions () {
this.options = genOptions()
},
regenValues () {
this.value = genValues()
}
}
}
</script>

View File

@ -202,6 +202,10 @@ export default {
{
name: 'Tooltip',
path: '/n-tooltip'
},
{
name: 'Transfer',
path: '/n-transfer'
}
]
},

View File

@ -51,6 +51,7 @@ import anchorDemo from './components/anchorDemo'
import popselectDemo from './components/popselectDemo'
import appDemo from './components/appDemo'
import advanceTableDemos from './components/advanceTableDemos'
import transferDemo from './components/transferDemo'
import demo from './demo'
@ -138,7 +139,8 @@ const routes = [
{ path: '/n-dropdown', component: dropdownDemo },
{ path: '/n-popselect', component: popselectDemo },
{ path: '/n-app', component: appDemo },
{ path: '/n-cancel-mark-debug', component: cancelMarkDebug }
{ path: '/n-cancel-mark-debug', component: cancelMarkDebug },
{ path: '/n-transfer', component: transferDemo }
]
},
{

View File

@ -81,6 +81,12 @@ Vue.use(naiveUi)
<td></td>
</tr>
<tr>
<td>TimePicker</td>
<td style="text-align:center;">😍</td>
<td style="text-align:center;"></td>
<td></td>
</tr>
<tr>
<td>GradientText</td>
<td style="text-align:center;">😍</td>
<td style="text-align:center;">🆗</td>
@ -135,24 +141,6 @@ Vue.use(naiveUi)
<td></td>
</tr>
<tr>
<td>FormItem</td>
<td style="text-align:center;">🚧</td>
<td style="text-align:center;"></td>
<td></td>
</tr>
<tr>
<td>Form</td>
<td style="text-align:center;">🚧</td>
<td style="text-align:center;"></td>
<td></td>
</tr>
<tr>
<td>Table</td>
<td style="text-align:center;">🚧</td>
<td style="text-align:center;"></td>
<td>Function is not fulfilled</td>
</tr>
<tr>
<td>Tooltip</td>
<td style="text-align:center;">😍</td>
<td style="text-align:center;"></td>
@ -178,13 +166,7 @@ Vue.use(naiveUi)
</tr>
<tr>
<td>Tab</td>
<td style="text-align:center;">🚧</td>
<td style="text-align:center;"></td>
<td></td>
</tr>
<tr>
<td>Breadcrumb</td>
<td style="text-align:center;">🚧</td>
<td style="text-align:center;">😍</td>
<td style="text-align:center;"></td>
<td></td>
</tr>
@ -213,24 +195,12 @@ Vue.use(naiveUi)
<td></td>
</tr>
<tr>
<td>Statistic</td>
<td style="text-align:center;">🚧</td>
<td style="text-align:center;"></td>
<td></td>
</tr>
<tr>
<td>Popconfirm</td>
<td style="text-align:center;">😍</td>
<td style="text-align:center;"></td>
<td></td>
</tr>
<tr>
<td>Anchor</td>
<td style="text-align:center;">🚧</td>
<td style="text-align:center;"></td>
<td></td>
</tr>
<tr>
<td>BackTop</td>
<td style="text-align:center;">😍</td>
<td style="text-align:center;"></td>
@ -249,12 +219,6 @@ Vue.use(naiveUi)
<td></td>
</tr>
<tr>
<td>Card</td>
<td style="text-align:center;">🚧</td>
<td style="text-align:center;"></td>
<td></td>
</tr>
<tr>
<td>Collapse</td>
<td style="text-align:center;">😍</td>
<td style="text-align:center;"></td>
@ -262,7 +226,13 @@ Vue.use(naiveUi)
</tr>
<tr>
<td>Cascader</td>
<td style="text-align:center;">🚧</td>
<td style="text-align:center;">😍</td>
<td style="text-align:center;"></td>
<td></td>
</tr>
<tr>
<td>Dropdown</td>
<td style="text-align:center;">😍</td>
<td style="text-align:center;"></td>
<td></td>
</tr>
@ -272,6 +242,120 @@ Vue.use(naiveUi)
<td style="text-align:center;"></td>
<td></td>
</tr>
<tr>
<td>Transfer</td>
<td style="text-align:center;">🚧</td>
<td style="text-align:center;"></td>
<td></td>
</tr>
<tr>
<td>Carousel</td>
<td style="text-align:center;">🚧</td>
<td style="text-align:center;"></td>
<td></td>
</tr>
<tr>
<td>Grid</td>
<td style="text-align:center;">🚧</td>
<td style="text-align:center;"></td>
<td></td>
</tr>
<tr>
<td>Card</td>
<td style="text-align:center;">🚧</td>
<td style="text-align:center;"></td>
<td></td>
</tr>
<tr>
<td>Anchor</td>
<td style="text-align:center;">🚧</td>
<td style="text-align:center;"></td>
<td></td>
</tr>
<tr>
<td>Statistic</td>
<td style="text-align:center;">🚧</td>
<td style="text-align:center;"></td>
<td></td>
</tr>
<tr>
<td>Breadcrumb</td>
<td style="text-align:center;">🚧</td>
<td style="text-align:center;"></td>
<td></td>
</tr>
<tr>
<td>FormItem</td>
<td style="text-align:center;">🚧</td>
<td style="text-align:center;"></td>
<td></td>
</tr>
<tr>
<td>Form</td>
<td style="text-align:center;">🚧</td>
<td style="text-align:center;"></td>
<td></td>
</tr>
<tr>
<td>Table</td>
<td style="text-align:center;">🚧</td>
<td style="text-align:center;"></td>
<td>Function is not fulfilled</td>
</tr>
<tr>
<td>AutoComplete</td>
<td style="text-align:center;">🚧</td>
<td style="text-align:center;"></td>
<td></td>
</tr>
<tr>
<td>Slider</td>
<td style="text-align:center;">🚧</td>
<td style="text-align:center;"></td>
<td></td>
</tr>
<tr>
<td>TreeSelect</td>
<td style="text-align:center;">🚧</td>
<td style="text-align:center;"></td>
<td></td>
</tr>
<tr>
<td>Transfer</td>
<td style="text-align:center;">🚧</td>
<td style="text-align:center;"></td>
<td></td>
</tr>
<tr>
<td>Upload</td>
<td style="text-align:center;">🚧</td>
<td style="text-align:center;"></td>
<td></td>
</tr>
<tr>
<td>Empty</td>
<td style="text-align:center;">🚧</td>
<td style="text-align:center;"></td>
<td></td>
</tr>
<tr>
<td>Tree</td>
<td style="text-align:center;">🚧</td>
<td style="text-align:center;"></td>
<td></td>
</tr>
<tr>
<td>Spin</td>
<td style="text-align:center;">🚧</td>
<td style="text-align:center;"></td>
<td></td>
</tr>
<tr>
<td>Drawer</td>
<td style="text-align:center;">🚧</td>
<td style="text-align:center;"></td>
<td></td>
</tr>
</tbody>
</table>
<ol>
@ -284,4 +368,21 @@ Vue.use(naiveUi)
<li>Refactor documentation page(for code clairity)</li>
<li>Code refactor for some 😢 messy code(which is my bad)</li>
<li>Refactor CSS use mixins(which means I should learn SCSS hard)</li>
</ol></div>`
</ol>
<h2 id="roadmap">RoadMap</h2>
<p>v0.3 cascader
v0.4 refactor popover
v0.5 finish all planned components
v0.6 add keyboard event on planned components
v0.7 refactor form component
v0.8 refactor table component
v0.9 fulfill props for all components
v0.10 split icons for components
v0.11 refactor css
v0.12 import on demand
v0.13 i18n
v0.14 unit test
v0.15 light theme
v0.16 refactor using proper html tags
v0.17 document formation
v0.18 refactor document page</p></div>`

View File

@ -51,6 +51,7 @@ import Dropdown from './packages/common/Dropdown'
import Popselect from './packages/common/Popselect'
import App from './packages/common/App'
import CancelMark from './packages/base/CancelMark'
import Transfer from './packages/common/Transfer'
function install (Vue) {
Card.install(Vue)
@ -106,6 +107,7 @@ function install (Vue) {
Popselect.install(Vue)
App.install(Vue)
CancelMark.install(Vue)
Transfer.install(Vue)
}
export default {

View File

@ -0,0 +1,8 @@
/* istanbul ignore file */
import Transfer from './src/main.vue'
Transfer.install = function (Vue) {
Vue.component(Transfer.name, Transfer)
}
export default Transfer

View File

@ -0,0 +1,58 @@
<template>
<li
class="n-transfer-list-item"
@click="handleClick"
>
<div class="n-transfer-list-item__checkbox">
<n-checkbox
:value="checked"
@input="handleInput"
/>
</div>
<slot />
</li>
</template>
<script>
import NCheckbox from '../../Checkbox'
export default {
name: 'NTransferListItem',
components: {
NCheckbox
},
props: {
checked: {
type: Boolean,
required: true
},
value: {
validator () {
return true
},
required: true
}
},
data () {
return {
show: false
}
},
computed: {
transitionName () {
return this.source ? 'n-transfer-list-item-source--transition' : 'n-transfer-list-item-target--transition'
}
},
mounted () {
this.show = true
},
methods: {
handleClick () {
this.$emit('click')
},
handleInput (checked) {
this.$emit('input', checked, this.value)
}
}
}
</script>

View File

@ -0,0 +1,257 @@
<template>
<div class="n-transfer">
<div class="n-transfer-list">
<div class="n-transfer-list-header">
<div class="n-transfer-list-header__checkbox">
<n-checkbox
:value="sourceHeaderCheckboxChecked"
:indeterminate="sourceHeaderCheckboxIndeterminate"
@input="handleSourceHeaderCheckboxInput"
/>
</div>
<div class="n-transfer-list-header__header">
Source
</div>
<div class="n-transfer-list-header__label">
{{ sourceCheckedValueSet.size }} / {{ sourceOptions.length }}
</div>
</div>
<div class="n-transfer-list-body">
<n-scrollbar ref="leftScrollbar">
<ul class="n-transfer-list-body-content">
<transition
v-for="option in memorizedOptions"
:key="option.value"
name="n-transfer-list-item-source--transition"
>
<n-transfer-list-item
v-if="sourceValueSet.has(option.value)"
:value="option.value"
:checked="sourceCheckedValueSet.has(option.value)"
@click="handleSourceCheckboxInput(
!sourceCheckedValueSet.has(option.value),
option.value
)"
>
{{ option.label }}
</n-transfer-list-item>
</transition>
</ul>
</n-scrollbar>
</div>
</div>
<div class="n-transfer-actions">
<button @click="handleToTargetClick">
To Target
</button>
<button @click="handleToSourceClick">
To Source
</button>
</div>
<div class="n-transfer-list">
<div class="n-transfer-list-header">
<div class="n-transfer-list-header__checkbox">
<n-checkbox
:value="targetHeaderCheckboxChecked"
:indeterminate="targetHeaderCheckboxIndeterminate"
@input="handleTargetHeaderCheckboxInput"
/>
</div>
<div class="n-transfer-list-header__header">
Target
</div>
<div class="n-transfer-list-header__label">
{{ targetCheckedValueSet.size }} / {{ targetOptions.length }}
</div>
</div>
<div class="n-transfer-list-body">
<n-scrollbar ref="rightScrollbar">
<ul class="n-transfer-list-body-content">
<transition
v-for="option in memorizedOptions"
:key="option.value"
name="n-transfer-list-item-target--transition"
>
<n-transfer-list-item
v-if="targetValueSet.has(option.value)"
:value="option.value"
:checked="targetCheckedValueSet.has(option.value)"
@click="handleTargetCheckboxInput(
!targetCheckedValueSet.has(option.value),
option.value
)"
>
{{ option.label }}
</n-transfer-list-item>
</transition>
</ul>
</n-scrollbar>
</div>
</div>
</div>
</template>
<script>
import NCheckbox from '../../Checkbox'
import NScrollbar from '../../Scrollbar'
import NTransferListItem from './TransferListItem'
export default {
name: 'NTransfer',
components: {
NCheckbox,
NScrollbar,
NTransferListItem
},
props: {
value: {
type: Array,
default: null
},
options: {
type: Array,
default: () => []
}
},
data () {
return {
sourceCheckedValues: [],
targetCheckedValues: [],
memorizedOptions: null,
init: true
}
},
computed: {
sourceHeaderCheckboxChecked () {
return this.sourceCheckedValueSet.size === this.sourceOptions.length && !!this.sourceOptions.length
},
targetHeaderCheckboxChecked () {
return this.targetCheckedValueSet.size === this.targetOptions.length && !!this.targetOptions.length
},
valueToOptionMap () {
const map = new Map()
this.memorizedOptions.forEach(option => {
map.set(option.value, option)
})
return map
},
sourceHeaderCheckboxIndeterminate () {
return this.sourceCheckedValueSet.size !== 0 && this.sourceCheckedValueSet.size < this.sourceOptions.length
},
targetHeaderCheckboxIndeterminate () {
return this.targetCheckedValueSet.size !== 0 && this.targetCheckedValueSet.size < this.targetOptions.length
},
sourceValueSet () {
return new Set(this.sourceOptions.map(option => option.value))
},
targetValueSet () {
return new Set(this.targetOptions.map(option => option.value))
},
sourceCheckedValueSet () {
return new Set(this.sourceCheckedValues.filter(value => this.valueToOptionMap.has(value)))
},
targetCheckedValueSet () {
return new Set(this.targetCheckedValues.filter(value => this.valueToOptionMap.has(value)))
},
sourceOptions () {
const valueSet = Array.isArray(this.value) ? new Set(this.value) : new Set()
return this.memorizedOptions.filter(option => !valueSet.has(option.value))
},
targetOptions () {
const value = Array.isArray(this.value) ? this.value : []
return value.filter(v => this.valueToOptionMap.has(v)).map(v => this.valueToOptionMap.get(v))
},
orderedOptions () {
return this.sourceOptions.concat(this.targetOptions)
}
},
watch: {
options (newOptions) {
this.init = true
this.$nextTick().then(() => {
this.memorizedOptions = newOptions
this.sourceCheckedValues = []
this.targetCheckedValues = []
return this.$nextTick()
}).then(() => {
this.init = false
})
}
},
mounted () {
this.$nextTick().then(() => {
this.init = false
})
},
created () {
this.memorizedOptions = this.options
},
methods: {
emitInputEvent (value) {
this.$emit('input', this.cleanValue(value))
},
cleanValue (value) {
if (Array.isArray(value)) {
return value.filter((v) => this.valueToOptionMap.has(v))
} else return null
},
handleSourceHeaderCheckboxInput (value) {
if (this.sourceHeaderCheckboxIndeterminate) {
this.sourceCheckedValues = []
return
}
if (value) {
this.sourceCheckedValues = this.sourceOptions.map(option => option.value)
} else {
this.sourceCheckedValues = []
}
},
handleTargetHeaderCheckboxInput (value) {
if (this.targetHeaderCheckboxIndeterminate) {
this.targetCheckedValues = []
return
}
if (value) {
this.targetCheckedValues = this.targetOptions.map(option => option.value)
} else {
this.targetCheckedValues = []
}
},
handleTargetCheckboxInput (checked, value) {
if (checked) {
this.targetCheckedValues.push(value)
} else {
const index = this.targetCheckedValues.findIndex(v => v === value)
if (~index) this.targetCheckedValues.splice(index, 1)
}
},
handleSourceCheckboxInput (checked, value) {
if (checked) {
this.sourceCheckedValues.push(value)
} else {
const index = this.sourceCheckedValues.findIndex(v => v === value)
if (~index) this.sourceCheckedValues.splice(index, 1)
}
},
handleToTargetClick () {
let newValue = Array.isArray(this.value) ? this.value : []
newValue = this.sourceCheckedValues.concat(newValue)
this.emitInputEvent(newValue)
this.sourceCheckedValues = []
},
handleToSourceClick () {
let newValue = Array.isArray(this.value) ? this.value : []
newValue = newValue.filter(value => this.valueToOptionMap.has(value))
const filteredValues = newValue.filter(value => this.targetCheckedValueSet.has(value))
const stayedValues = newValue.filter(value => !this.targetCheckedValueSet.has(value))
newValue = stayedValues
const reorderedOptionsFirstPart = filteredValues.concat(stayedValues).map(value => this.valueToOptionMap.get(value))
const reorderedOptionsSecondPart = this.memorizedOptions.filter(option => !filteredValues.includes(option.value) && !stayedValues.includes(option.value))
const reorderedOptions = reorderedOptionsFirstPart.concat(reorderedOptionsSecondPart)
this.memorizedOptions = reorderedOptions
this.emitInputEvent(stayedValues)
this.targetCheckedValues = []
}
}
}
</script>

View File

@ -169,16 +169,20 @@
&.n-base-picker--disabled {
cursor: not-allowed;
.n-base-picker-label, .n-base-picker-tags {
cursor: not-allowed;
background-color: rgba(255, 255, 255, 0.08);
}
.n-base-picker-tag {
cursor: not-allowed;
border-color: rgba(255, 255, 255, 0.20);
color: rgba(255, 255, 255, 0.20);
}
.n-base-picker__placeholder {
cursor: not-allowed;
color: rgba(255, 255, 255, 0.20);
}
.n-base-picker-label__input {
cursor: not-allowed;
color: rgba(255, 255, 255, 0.20);
&.n-base-picker-label__input--placeholder {
color: rgba(255, 255, 255, 0.20);
@ -225,7 +229,7 @@
}
.n-base-picker-input-tag__mirror {
position: absolute;
padding-right: .5em;
padding-right: 1em;
left: 0;
top: 0;
white-space: pre;

79
styles/Transfer.scss Normal file
View File

@ -0,0 +1,79 @@
@import './mixins/mixins.scss';
@import './theme/default.scss';
@include b(transfer) {
display: flex;
@include b(transfer-list) {
width: 182px;
height: 312px;
background-color: rgba(75,81,106,1);
border-radius: 6px;
@include b(transfer-list-header) {
background:rgba(255,255,255,0.2);
display: flex;
border-radius: 6px 6px 0 0;
align-items: center;
height: 40px;
@include e(checkbox) {
position: relative;
padding: 0 8px 0 14px;
@include b(checkbox) {
display: block;
}
}
@include e(header) {
flex: 1;
line-height: 1;
font-size: 16px;
font-weight: bold;
color: rgba(255, 255, 255, 1);
@include m(disabled) {
color: rgba(255, 255, 255, 0.25);
}
}
@include e(label) {
font-size: 12px;
justify-self: flex-end;
margin-right: 14px;
}
}
@include b(transfer-list-body) {
overflow: hidden;
position: relative;
height: 272px;
@include b(transfer-list-body-content) {
padding: 0;
margin: 0;
@include b(transfer-list-item) {
@include slide-right-transition(transfer-list-item-source, 2s);
@include slide-left-transition(transfer-list-item-target, 2s);
cursor: pointer;
max-height: 34px;
display: flex;
align-items: center;
font-size: 14px;
height: 34px;
color: rgba(255, 255, 255, 1);
@include e(checkbox) {
position: relative;
padding: 0 8px 0 14px;
@include b(checkbox) {
display: block;
}
}
@include m(disabled) {
color: rgba(255, 255, 255, 0.25);
cursor: not-allowed;
}
@include m(selected) {
color: rgba(99, 226, 183, 1);
}
}
}
}
}
@include b(transfer-actions) {
}
}

View File

@ -42,6 +42,7 @@
@import './BaseCancelMark.scss';
@import './BasePicker.scss';
@import './BaseSelectMenu.scss';
@import './Transfer.scss';
@import "./NimbusServiceLayout.scss";
@import "./Popover.scss";

View File

@ -1,11 +1,35 @@
@import "./config.scss";
@mixin b($block) {
$B: $namespace + "-" + $block;
$B: null;
$BE: null;
$BEM: null;
@mixin b($block) {
$temp-block: $B;
$temp-block-element: $BE;
$B: $namespace + "-" + $block !global;
$BE: $B!global;
.#{$B} {
@content;
}
$B: $temp-block !global;
$BE: $temp-block-element !global;
}
@mixin e($element) {
$temp-block-element: $BE;
$BE: $B + "__" + $element !global;
.#{$BE} {
@content
}
$BE: $temp-block-element !global;
}
@mixin m($modifier) {
$BEM: $BE + '--' + $modifier;
&.#{$BEM} {
@content
}
}
@mixin detachedContentWrapper {

View File

@ -218,4 +218,50 @@ $scrollbar-color--hover: rgba(255,255,255,0.3);
&.#{$namespace}-#{$block}--transition-leave-to {
transition: opacity $duration $default-cubic-bezier;
}
}
@mixin slide-right-transition($block, $duration: .2s, $delay: .2s) {
&.#{$namespace}-#{$block}--transition-leave-active {
transition: transform $duration $slow-out-cubic-bezier, max-height $duration $default-cubic-bezier $delay;
}
&.#{$namespace}-#{$block}--transition-enter-active {
transition: transform $duration $fast-in-cubic-bezier $delay, max-height $duration $default-cubic-bezier;
}
&.#{$namespace}-#{$block}--transition-enter-to {
transform: translateX(0);
}
&.#{$namespace}-#{$block}--transition-enter {
transform: translateX(150%);
max-height: 0;
}
&.#{$namespace}-#{$block}--transition-leave {
transform: translateX(0);
}
&.#{$namespace}-#{$block}--transition-leave-to {
transform: translateX(150%);
max-height: 0;
}
}
@mixin slide-left-transition($block, $duration: .2s, $delay: .2s) {
&.#{$namespace}-#{$block}--transition-leave-active {
transition: transform $duration $slow-out-cubic-bezier, max-height $duration $default-cubic-bezier $delay;
}
&.#{$namespace}-#{$block}--transition-enter-active {
transition: transform $duration $fast-in-cubic-bezier $delay, max-height $duration $default-cubic-bezier;
}
&.#{$namespace}-#{$block}--transition-enter-to {
transform: translateX(0);
}
&.#{$namespace}-#{$block}--transition-enter {
transform: translateX(-150%);
max-height: 0;
}
&.#{$namespace}-#{$block}--transition-leave {
transform: translateX(0);
}
&.#{$namespace}-#{$block}--transition-leave-to {
transform: translateX(-150%);
max-height: 0;
}
}