diff --git a/docs/demos/index.js b/docs/demos/index.js
index 8e85dba4b..9976b69d0 100644
--- a/docs/demos/index.js
+++ b/docs/demos/index.js
@@ -33,6 +33,7 @@ export default {
'cell': asyncWrapper(r => require.ensure([], () => r(componentWrapper(require('./views/cell'), 'cell')), 'cell')),
'checkbox': asyncWrapper(r => require.ensure([], () => r(componentWrapper(require('./views/checkbox'), 'checkbox')), 'checkbox')),
'circle': asyncWrapper(r => require.ensure([], () => r(componentWrapper(require('./views/circle'), 'circle')), 'circle')),
+ 'collapse': asyncWrapper(r => require.ensure([], () => r(componentWrapper(require('./views/collapse'), 'collapse')), 'collapse')),
'contact': asyncWrapper(r => require.ensure([], () => r(componentWrapper(require('./views/contact'), 'contact')), 'contact')),
'coupon': asyncWrapper(r => require.ensure([], () => r(componentWrapper(require('./views/coupon'), 'coupon')), 'coupon')),
'datetime-picker': asyncWrapper(r => require.ensure([], () => r(componentWrapper(require('./views/datetime-picker'), 'datetime-picker')), 'datetime-picker')),
diff --git a/docs/demos/views/collapse.vue b/docs/demos/views/collapse.vue
new file mode 100644
index 000000000..990a19393
--- /dev/null
+++ b/docs/demos/views/collapse.vue
@@ -0,0 +1,83 @@
+
+
+
+
+ {{ $t('content1') }}
+ {{ $t('content2') }}
+ {{ $t('content3') }}
+
+
+
+
+
+ {{ $t('content1') }}
+ {{ $t('content2') }}
+ {{ $t('content3') }}
+
+
+
+
+
+
+ {{ $t('title1') }}
+ {{ $t('content1') }}
+
+ {{ $t('content2') }}
+
+
+
+
+
+
+
+
diff --git a/docs/markdown/en-US/collapse.md b/docs/markdown/en-US/collapse.md
new file mode 100644
index 000000000..05d241111
--- /dev/null
+++ b/docs/markdown/en-US/collapse.md
@@ -0,0 +1,95 @@
+## Collapse
+
+### Install
+``` javascript
+import { Collapse } from 'vant';
+
+Vue.use(Collapse);
+```
+
+### Usage
+
+#### Basic Usage
+Use `v-model` to control the name of active panels
+
+```html
+
+ Content
+ Content
+ Content
+
+```
+
+``` javascript
+export default {
+ data() {
+ return {
+ activeNames: ['1']
+ };
+ }
+};
+```
+
+#### Accordion
+In accordion mode, only one panel can be expanded at the same time.
+
+```html
+
+ Content
+ Content
+ Content
+
+```
+
+``` javascript
+export default {
+ data() {
+ return {
+ activeName: '1'
+ };
+ }
+};
+```
+
+#### Custom title
+
+```html
+
+
+ Title1
+ Content
+
+
+ Content
+
+
+```
+
+
+
+### Collapse API
+
+| Attribute | Description | Type | Default | Accepted Values |
+|-----------|-----------|-----------|-------------|-------------|
+| v-model | names of current active panels | `Array | String | Number` | - | - |
+| accordion | Whether to be accordion mode | `Boolean` | `false` | - |
+
+### Collapse Event
+
+| Event | Description | Arguments |
+|-----------|-----------|-----------|
+| change | Triggered when switch panel | activeNames: `string | array` |
+
+### CollapseItem API
+
+| Attribute | Description | Type | Default | Accepted Values |
+|-----------|-----------|-----------|-------------|-------------|
+| name | Name | `String | Number` | `index` | - |
+| title | Title | `String` | - | - |
+
+### CollapseItem Slot
+
+| name | Description |
+|-----------|-----------|
+| default | Content |
+| title | Custom title |
\ No newline at end of file
diff --git a/docs/markdown/index.js b/docs/markdown/index.js
index 16830af2c..17f923054 100644
--- a/docs/markdown/index.js
+++ b/docs/markdown/index.js
@@ -27,6 +27,7 @@ export default {
'zh-CN/changelog': wrapper(r => require.ensure([], () => r(require('./zh-CN/changelog.md')), 'zh-CN/changelog')),
'zh-CN/checkbox': wrapper(r => require.ensure([], () => r(require('./zh-CN/checkbox.md')), 'zh-CN/checkbox')),
'zh-CN/circle': wrapper(r => require.ensure([], () => r(require('./zh-CN/circle.md')), 'zh-CN/circle')),
+ 'zh-CN/collapse': wrapper(r => require.ensure([], () => r(require('./zh-CN/collapse.md')), 'zh-CN/collapse')),
'zh-CN/contact': wrapper(r => require.ensure([], () => r(require('./zh-CN/contact.md')), 'zh-CN/contact')),
'zh-CN/coupon': wrapper(r => require.ensure([], () => r(require('./zh-CN/coupon.md')), 'zh-CN/coupon')),
'zh-CN/datetime-picker': wrapper(r => require.ensure([], () => r(require('./zh-CN/datetime-picker.md')), 'zh-CN/datetime-picker')),
@@ -81,6 +82,7 @@ export default {
'en-US/changelog': wrapper(r => require.ensure([], () => r(require('./en-US/changelog.md')), 'en-US/changelog')),
'en-US/checkbox': wrapper(r => require.ensure([], () => r(require('./en-US/checkbox.md')), 'en-US/checkbox')),
'en-US/circle': wrapper(r => require.ensure([], () => r(require('./en-US/circle.md')), 'en-US/circle')),
+ 'en-US/collapse': wrapper(r => require.ensure([], () => r(require('./en-US/collapse.md')), 'en-US/collapse')),
'en-US/contact': wrapper(r => require.ensure([], () => r(require('./en-US/contact.md')), 'en-US/contact')),
'en-US/coupon': wrapper(r => require.ensure([], () => r(require('./en-US/coupon.md')), 'en-US/coupon')),
'en-US/datetime-picker': wrapper(r => require.ensure([], () => r(require('./en-US/datetime-picker.md')), 'en-US/datetime-picker')),
diff --git a/docs/markdown/zh-CN/collapse.md b/docs/markdown/zh-CN/collapse.md
new file mode 100644
index 000000000..539549d52
--- /dev/null
+++ b/docs/markdown/zh-CN/collapse.md
@@ -0,0 +1,108 @@
+## Collapse 折叠面板
+
+### 使用指南
+``` javascript
+import { Collapse } from 'vant';
+
+Vue.use(Collapse);
+```
+
+### 代码演示
+
+#### 基础用法
+通过`v-model`控制展开的面板列表,`activeNames`为数组格式
+
+```html
+
+
+ 提供多样店铺模板,快速搭建网上商城
+
+
+ 网店吸粉获客、会员分层营销、一机多种收款,告别经营低效和客户流失
+
+
+ 线上拓客,随时预约,贴心顺手的开单收银
+
+
+```
+
+``` javascript
+export default {
+ data() {
+ return {
+ activeNames: ['1']
+ };
+ }
+};
+```
+
+#### 手风琴
+通过`accordion`可以设置为手风琴模式,最多展开一个面板,此时`activeName`为字符串格式
+
+```html
+
+
+ 提供多样店铺模板,快速搭建网上商城
+
+
+ 网店吸粉获客、会员分层营销、一机多种收款,告别经营低效和客户流失
+
+
+ 线上拓客,随时预约,贴心顺手的开单收银
+
+
+```
+
+``` javascript
+export default {
+ data() {
+ return {
+ activeName: '1'
+ };
+ }
+};
+```
+
+#### 自定义标题内容
+
+```html
+
+
+ 有赞微商城
+ 提供多样店铺模板,快速搭建网上商城
+
+
+ 网店吸粉获客、会员分层营销、一机多种收款,告别经营低效和客户流失
+
+
+```
+
+
+
+### Collapse API
+
+| 参数 | 说明 | 类型 | 默认值 | 可选值 |
+|-----------|-----------|-----------|-------------|-------------|
+| v-model | 当前展开面板的 name | `Array | String | Number` | - | - |
+| accordion | 是否开启手风琴模式 | `Boolean` | `false` | - |
+
+### Collapse Event
+
+| 事件名 | 说明 | 参数 |
+|-----------|-----------|-----------|
+| change | 切换面板时触发 | activeNames: `string | array` |
+
+### CollapseItem API
+
+| 参数 | 说明 | 类型 | 默认值 | 可选值 |
+|-----------|-----------|-----------|-------------|-------------|
+| name | 面板唯一标识符,默认为索引值 | `String | Number` | `index` | - |
+| title | 标题 | `String` | - | - |
+
+
+### CollapseItem Slot
+
+| 名称 | 说明 |
+|-----------|-----------|
+| default | 面板内容 |
+| title | 自定义标题内容 |
\ No newline at end of file
diff --git a/docs/src/doc.config.js b/docs/src/doc.config.js
index 1cad7cce2..334e3d7f9 100644
--- a/docs/src/doc.config.js
+++ b/docs/src/doc.config.js
@@ -88,6 +88,10 @@ module.exports = {
path: '/circle',
title: 'Circle - 环形进度条'
},
+ {
+ path: '/collapse',
+ title: 'Collapse - 折叠面板'
+ },
{
path: '/icon',
title: 'Icon - 图标'
@@ -374,6 +378,10 @@ module.exports = {
path: '/circle',
title: 'Circle'
},
+ {
+ path: '/collapse',
+ title: 'Collapse'
+ },
{
path: '/icon',
title: 'Icon'
diff --git a/packages/address-edit/Detail.vue b/packages/address-edit/Detail.vue
index 891db7bf1..3b4dc0df8 100644
--- a/packages/address-edit/Detail.vue
+++ b/packages/address-edit/Detail.vue
@@ -11,8 +11,8 @@
:error="isError"
:on-icon-click="onIconClick"
@input="$emit('input', $event)"
- @focus="handleFocus"
- @blur="handleBlur"
+ @focus="onFocus"
+ @blur="onBlur"
>
{{ $t('complete') }}
@@ -79,13 +79,13 @@ export default create({
},
methods: {
- handleFocus(e) {
+ onFocus(e) {
this.isFocused = true;
this.$emit('focus', e);
this.$refs.root.scrollIntoView();
},
- handleBlur(e) {
+ onBlur(e) {
// wait for click event finished
setTimeout(() => {
this.isFocused = false;
diff --git a/packages/collapse-item/index.vue b/packages/collapse-item/index.vue
new file mode 100644
index 000000000..50cc6cf61
--- /dev/null
+++ b/packages/collapse-item/index.vue
@@ -0,0 +1,75 @@
+
+
+
+ {{ title }}
+ |
+
+
+
+
+
+
+
diff --git a/packages/collapse/index.vue b/packages/collapse/index.vue
new file mode 100644
index 000000000..7d526bbe4
--- /dev/null
+++ b/packages/collapse/index.vue
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
diff --git a/packages/index.js b/packages/index.js
index f6be54972..8930ee40d 100644
--- a/packages/index.js
+++ b/packages/index.js
@@ -14,6 +14,8 @@ import Checkbox from './checkbox';
import CheckboxGroup from './checkbox-group';
import Circle from './circle';
import Col from './col';
+import Collapse from './collapse';
+import CollapseItem from './collapse-item';
import ContactCard from './contact-card';
import ContactEdit from './contact-edit';
import ContactList from './contact-list';
@@ -80,6 +82,8 @@ const components = [
CheckboxGroup,
Circle,
Col,
+ Collapse,
+ CollapseItem,
ContactCard,
ContactEdit,
ContactList,
@@ -153,6 +157,8 @@ export {
CheckboxGroup,
Circle,
Col,
+ Collapse,
+ CollapseItem,
ContactCard,
ContactEdit,
ContactList,
diff --git a/packages/vant-css/src/collapse.css b/packages/vant-css/src/collapse.css
new file mode 100644
index 000000000..c796efa0c
--- /dev/null
+++ b/packages/vant-css/src/collapse.css
@@ -0,0 +1,31 @@
+@import './common/var.css';
+
+.van-collapse-item {
+ &__title {
+ .van-cell__right-icon::before {
+ transition: .3s;
+ transform: rotate(90deg);
+ }
+
+ &::after {
+ visibility: hidden;
+ }
+ }
+
+ &__content {
+ padding: 15px;
+ background-color: #fff;
+ }
+
+ &--expanded {
+ .van-collapse-item__title {
+ .van-cell__right-icon::before {
+ transform: rotate(-90deg);
+ }
+
+ &::after {
+ visibility: visible;
+ }
+ }
+ }
+}
diff --git a/packages/vant-css/src/index.css b/packages/vant-css/src/index.css
index e2f140575..e66642101 100644
--- a/packages/vant-css/src/index.css
+++ b/packages/vant-css/src/index.css
@@ -13,6 +13,7 @@
@import './button.css';
@import './cell.css';
@import './circle.css';
+@import './collapse.css';
@import './loading.css';
@import './nav-bar.css';
@import './notice-bar.css';
diff --git a/test/components/collapse.vue b/test/components/collapse.vue
new file mode 100644
index 000000000..56e29f7ce
--- /dev/null
+++ b/test/components/collapse.vue
@@ -0,0 +1,21 @@
+
+
+ content
+ content
+ content
+
+
+
+
diff --git a/test/specs/collapse.spec.js b/test/specs/collapse.spec.js
new file mode 100644
index 000000000..d1a702ad7
--- /dev/null
+++ b/test/specs/collapse.spec.js
@@ -0,0 +1,47 @@
+import { mount } from 'avoriaz';
+import Collapse from '../components/collapse';
+
+describe('Circle', () => {
+ let wrapper;
+ afterEach(() => {
+ wrapper && wrapper.destroy();
+ });
+
+ it('basic mode', () => {
+ wrapper = mount(Collapse);
+
+ const firstTitle = wrapper.find('.van-collapse-item__title')[0];
+ firstTitle.trigger('click');
+ expect(wrapper.vm.active).to.eql(['first']);
+
+ const secondTitle = wrapper.find('.van-collapse-item__title')[1];
+ secondTitle.trigger('click');
+ expect(wrapper.vm.active).to.eql(['first', 1]);
+
+ firstTitle.trigger('click');
+ expect(wrapper.vm.active).to.eql([1]);
+ });
+
+ it('accordion', () => {
+ wrapper = mount(Collapse, {
+ propsData: {
+ accordion: true
+ }
+ });
+
+ const firstTitle = wrapper.find('.van-collapse-item__title')[0];
+ firstTitle.trigger('click');
+ expect(wrapper.vm.active).to.eql('first');
+
+ const secondTitle = wrapper.find('.van-collapse-item__title')[1];
+ secondTitle.trigger('click');
+ expect(wrapper.vm.active).to.eql(1);
+
+ firstTitle.trigger('click');
+ expect(wrapper.vm.active).to.eql('first');
+
+ firstTitle.trigger('click');
+ expect(wrapper.vm.active).to.eql('');
+ });
+});
+