diff --git a/components.json b/components.json index ae845177e..956ecebec 100644 --- a/components.json +++ b/components.json @@ -55,5 +55,7 @@ "steps": "./packages/steps/index.js", "step": "./packages/step/index.js", "carousel": "./packages/carousel/index.js", - "carousel-item": "./packages/carousel-item/index.js" + "carousel-item": "./packages/carousel-item/index.js", + "collapse": "./packages/collapse/index.js", + "collapse-item": "./packages/collapse-item/index.js" } diff --git a/examples/docs/en-US/collapse.md b/examples/docs/en-US/collapse.md new file mode 100644 index 000000000..84171e1ca --- /dev/null +++ b/examples/docs/en-US/collapse.md @@ -0,0 +1,150 @@ + + + +## Collapse + +Use Collapse to storage content. + +### Basic usage + +可同时展开多个面板,面板之间不影响 + +:::demo +```html + + +
与现实生活一致:与现实生活的流程、逻辑保持一致,遵循用户习惯的语言和概念;
+
在界面中一致:所有的元素和结构需保持一致,比如:设计样式、图标和文本、元素的位置等。
+
+ +
控制反馈:通过界面样式和交互动效让用户可以清晰的感知自己的操作;
+
页面反馈:操作后,通过页面元素的变化清晰地展现当前状态。
+
+ +
简化流程:设计简洁直观的操作流程;
+
清晰明确:语言表达清晰且表意明确,让用户快速理解进而作出决策;
+
帮助用户识别:界面简单直白,让用户快速识别而非回忆,减少用户记忆负担。
+
+ +
用户决策:根据场景可给予用户操作建议或安全提示,但不能代替用户进行决策;
+
结果可控:用户可以自由的进行操作,包括撤销、回退和终止当前操作等。
+
+
+ +``` +::: + +### Accordion + +At the same time only one item can be opened. + +:::demo 通过 `accordion` 属性来设置是否以手风琴模式显示。 +```html + + +
与现实生活一致:与现实生活的流程、逻辑保持一致,遵循用户习惯的语言和概念;
+
在界面中一致:所有的元素和结构需保持一致,比如:设计样式、图标和文本、元素的位置等。
+
+ +
控制反馈:通过界面样式和交互动效让用户可以清晰的感知自己的操作;
+
页面反馈:操作后,通过页面元素的变化清晰地展现当前状态。
+
+ +
简化流程:设计简洁直观的操作流程;
+
清晰明确:语言表达清晰且表意明确,让用户快速理解进而作出决策;
+
帮助用户识别:界面简单直白,让用户快速识别而非回忆,减少用户记忆负担。
+
+ +
用户决策:根据场景可给予用户操作建议或安全提示,但不能代替用户进行决策;
+
结果可控:用户可以自由的进行操作,包括撤销、回退和终止当前操作等。
+
+
+ +``` +::: + +### Customize Title + +除了可以通过 `title` 属性以外,还可以通过作用域插槽来实现自定义面板的标题内容,以实现增加图标等效果。 + +:::demo +```html + + + +
与现实生活一致:与现实生活的流程、逻辑保持一致,遵循用户习惯的语言和概念;
+
在界面中一致:所有的元素和结构需保持一致,比如:设计样式、图标和文本、元素的位置等。
+
+ +
控制反馈:通过界面样式和交互动效让用户可以清晰的感知自己的操作;
+
页面反馈:操作后,通过页面元素的变化清晰地展现当前状态。
+
+ +
简化流程:设计简洁直观的操作流程;
+
清晰明确:语言表达清晰且表意明确,让用户快速理解进而作出决策;
+
帮助用户识别:界面简单直白,让用户快速识别而非回忆,减少用户记忆负担。
+
+ +
用户决策:根据场景可给予用户操作建议或安全提示,但不能代替用户进行决策;
+
结果可控:用户可以自由的进行操作,包括撤销、回退和终止当前操作等。
+
+
+``` +::: + +### Collapse Attributes +| Attribute | Description | Type | Accepted Values | Default | +|---------- |-------------- |---------- |-------------------------------- |-------- | +| accordion | whether is accordion mode | boolean | — | false | +| value | the active item's name | string/array | — | — | + +### Collapse Events +| Event Name | Description | Parameters | +|---------|---------|---------| +| change | trigger when the active names change | (activeNames: array) | + +### Collapse Item Attributes +| Attribute | Description | Type | Accepted Values | Default | +|---------- |-------------- |---------- |-------------------------------- |-------- | +| name | unique identifier | string/number | — | — | +| title | title | string | — | — | \ No newline at end of file diff --git a/examples/docs/zh-CN/collapse.md b/examples/docs/zh-CN/collapse.md new file mode 100644 index 000000000..3264b5918 --- /dev/null +++ b/examples/docs/zh-CN/collapse.md @@ -0,0 +1,150 @@ + + + +## Collapse 折叠面板 + +通过折叠面板收纳内容区域 + +### 基础用法 + +可同时展开多个面板,面板之间不影响 + +:::demo +```html + + +
与现实生活一致:与现实生活的流程、逻辑保持一致,遵循用户习惯的语言和概念;
+
在界面中一致:所有的元素和结构需保持一致,比如:设计样式、图标和文本、元素的位置等。
+
+ +
控制反馈:通过界面样式和交互动效让用户可以清晰的感知自己的操作;
+
页面反馈:操作后,通过页面元素的变化清晰地展现当前状态。
+
+ +
简化流程:设计简洁直观的操作流程;
+
清晰明确:语言表达清晰且表意明确,让用户快速理解进而作出决策;
+
帮助用户识别:界面简单直白,让用户快速识别而非回忆,减少用户记忆负担。
+
+ +
用户决策:根据场景可给予用户操作建议或安全提示,但不能代替用户进行决策;
+
结果可控:用户可以自由的进行操作,包括撤销、回退和终止当前操作等。
+
+
+ +``` +::: + +### 手风琴效果 + +每次只能展开一个面板 + +:::demo 通过 `accordion` 属性来设置是否以手风琴模式显示。 +```html + + +
与现实生活一致:与现实生活的流程、逻辑保持一致,遵循用户习惯的语言和概念;
+
在界面中一致:所有的元素和结构需保持一致,比如:设计样式、图标和文本、元素的位置等。
+
+ +
控制反馈:通过界面样式和交互动效让用户可以清晰的感知自己的操作;
+
页面反馈:操作后,通过页面元素的变化清晰地展现当前状态。
+
+ +
简化流程:设计简洁直观的操作流程;
+
清晰明确:语言表达清晰且表意明确,让用户快速理解进而作出决策;
+
帮助用户识别:界面简单直白,让用户快速识别而非回忆,减少用户记忆负担。
+
+ +
用户决策:根据场景可给予用户操作建议或安全提示,但不能代替用户进行决策;
+
结果可控:用户可以自由的进行操作,包括撤销、回退和终止当前操作等。
+
+
+ +``` +::: + +### 自定义面板标题 + +除了可以通过 `title` 属性以外,还可以通过作用域插槽来实现自定义面板的标题内容,以实现增加图标等效果。 + +:::demo +```html + + + +
与现实生活一致:与现实生活的流程、逻辑保持一致,遵循用户习惯的语言和概念;
+
在界面中一致:所有的元素和结构需保持一致,比如:设计样式、图标和文本、元素的位置等。
+
+ +
控制反馈:通过界面样式和交互动效让用户可以清晰的感知自己的操作;
+
页面反馈:操作后,通过页面元素的变化清晰地展现当前状态。
+
+ +
简化流程:设计简洁直观的操作流程;
+
清晰明确:语言表达清晰且表意明确,让用户快速理解进而作出决策;
+
帮助用户识别:界面简单直白,让用户快速识别而非回忆,减少用户记忆负担。
+
+ +
用户决策:根据场景可给予用户操作建议或安全提示,但不能代替用户进行决策;
+
结果可控:用户可以自由的进行操作,包括撤销、回退和终止当前操作等。
+
+
+``` +::: + +### Collapse Attributes +| 参数 | 说明 | 类型 | 可选值 | 默认值 | +|---------- |-------------- |---------- |-------------------------------- |-------- | +| accordion | 是否手风琴模式 | boolean | — | false | +| value | 当前激活的面板 | string/array | — | — | + +### Collapse Events +| 事件名称 | 说明 | 回调参数 | +|---------|---------|---------| +| change | 当前激活面板改变时触发 | (activeNames: array) | + +### Collapse Item Attributes +| 参数 | 说明 | 类型 | 可选值 | 默认值 | +|---------- |-------------- |---------- |-------------------------------- |-------- | +| name | 唯一标志符 | string/number | — | — | +| title | 面板标题 | string | — | — | \ No newline at end of file diff --git a/examples/nav.config.json b/examples/nav.config.json index d697bf31f..d208122ae 100644 --- a/examples/nav.config.json +++ b/examples/nav.config.json @@ -211,6 +211,10 @@ { "path": "/carousel", "title": "Carousel 走马灯" + }, + { + "path": "/collapse", + "title": "Collapse 折叠面板" } ] } @@ -429,6 +433,10 @@ { "path": "/carousel", "title": "Carousel" + }, + { + "path": "/collapse", + "title": "Collapse" } ] } diff --git a/packages/collapse-item/index.js b/packages/collapse-item/index.js new file mode 100644 index 000000000..e94450044 --- /dev/null +++ b/packages/collapse-item/index.js @@ -0,0 +1,8 @@ +import ElCollapseItem from '../collapse/src/collapse-item.vue'; + +/* istanbul ignore next */ +ElCollapseItem.install = function(Vue) { + Vue.component(ElCollapseItem.name, ElCollapseItem); +}; + +export default ElCollapseItem; diff --git a/packages/collapse/_index.js b/packages/collapse/_index.js new file mode 100644 index 000000000..bdd970b27 --- /dev/null +++ b/packages/collapse/_index.js @@ -0,0 +1,13 @@ +import ElCollapse from './src/collapse'; +import ElCollapseItem from './src/collapse-item.vue'; + +/* istanbul ignore next */ +export default function install(Vue) { + Vue.component(ElCollapseItem.name, ElCollapseItem); + Vue.component(ElCollapse.name, ElCollapse); +}; + +export { + ElCollapse, + ElCollapseItem +}; diff --git a/packages/collapse/cooking.conf.js b/packages/collapse/cooking.conf.js new file mode 100644 index 000000000..db3d361de --- /dev/null +++ b/packages/collapse/cooking.conf.js @@ -0,0 +1,18 @@ +var cooking = require('cooking'); +var path = require('path'); +var config = require('../../build/config'); + +cooking.set({ + entry: { + index: path.join(__dirname, '_index.js') + }, + dist: path.join(__dirname, 'lib'), + template: false, + format: 'umd', + moduleName: 'ElCollapse', + extends: ['vue2'], + alias: config.alias, + externals: { vue: config.vue } +}); + +module.exports = cooking.resolve(); diff --git a/packages/collapse/index.js b/packages/collapse/index.js new file mode 100644 index 000000000..be490f8f2 --- /dev/null +++ b/packages/collapse/index.js @@ -0,0 +1,9 @@ +import ElCollapse from './src/collapse'; + +/* istanbul ignore next */ +ElCollapse.install = function(Vue) { + Vue.component(ElCollapse.name, ElCollapse); +}; + +export default ElCollapse; + diff --git a/packages/collapse/package.json b/packages/collapse/package.json new file mode 100644 index 000000000..af9c241eb --- /dev/null +++ b/packages/collapse/package.json @@ -0,0 +1,15 @@ +{ + "name": "element-collapse", + "version": "1.0.0", + "description": "A row component for Vue.", + "keywords": [ + "element", + "vue", + "component" + ], + "main": "./lib/index.js", + "repository": "https://github.com/ElemeFE/element/tree/master/packages/collapse", + "author": "haiping.zeng@ele.me", + "license": "MIT", + "dependencies": {} +} diff --git a/packages/collapse/src/collapse-item.vue b/packages/collapse/src/collapse-item.vue new file mode 100644 index 000000000..ec5268f5e --- /dev/null +++ b/packages/collapse/src/collapse-item.vue @@ -0,0 +1,106 @@ + + diff --git a/packages/collapse/src/collapse.vue b/packages/collapse/src/collapse.vue new file mode 100644 index 000000000..13b37e8e9 --- /dev/null +++ b/packages/collapse/src/collapse.vue @@ -0,0 +1,62 @@ + + diff --git a/packages/theme-default/src/collapse-item.css b/packages/theme-default/src/collapse-item.css new file mode 100644 index 000000000..e69de29bb diff --git a/packages/theme-default/src/collapse.css b/packages/theme-default/src/collapse.css new file mode 100644 index 000000000..b014302f7 --- /dev/null +++ b/packages/theme-default/src/collapse.css @@ -0,0 +1,52 @@ +@charset "UTF-8"; +@import "./common/var.css"; + +@component-namespace el { + @b collapse { + border: 1px solid var(--collapse-border-color); + border-radius: var(--collapse-border-radius); + } + @b collapse-item { + @e header { + height: var(--collapse-header-height); + line-height: @height; + padding-left: 15px; + background-color: var(--collapse-header-fill); + color: var(--collapse-header-color); + cursor: pointer; + border-bottom: 1px solid var(--collapse-border-color); + font-size: var(--collapse-header-size); + + @e arrow { + margin-right: 8px; + transition: transform .3s; + } + } + + @e wrap { + will-change: height; + background-color: var(--collapse-content-fill); + transition: height .3s cubic-bezier(0.215, 0.61, 0.355, 1); + overflow: hidden; + box-sizing: border-box; + border-bottom: 1px solid var(--collapse-border-color); + } + + @e content { + padding: 10px 15px; + font-size: var(--collapse-content-size); + color: var(--collapse-content-color); + line-height: 1.769230769230769; + } + + @when active { + .el-collapse-item__header__arrow { + transform: rotate(90deg); + } + } + + &:last-child { + margin-bottom: -1px; + } + } +} \ No newline at end of file diff --git a/packages/theme-default/src/common/var.css b/packages/theme-default/src/common/var.css index 6b5099f49..327bac8b8 100644 --- a/packages/theme-default/src/common/var.css +++ b/packages/theme-default/src/common/var.css @@ -556,4 +556,17 @@ --carousel-indicator-padding-horizontal: 4px; --carousel-indicator-padding-vertical: 12px; --carousel-indicator-out-color: var(--border-color-hover); + + /* Collapse + --------------------------*/ + --collapse-border-color: #e0e6ed; + --collapse-header-height: 43px; + --collapse-border-radius: 0; + --collapse-header-padding: 20px; + --collapse-header-fill: #fff; + --collapse-header-color: #475669; + --collapse-header-size: 13px; + --collapse-content-fill: #f9fafc; + --collapse-content-size: 13px; + --collapse-content-color: #1f2d3d; } diff --git a/packages/theme-default/src/index.css b/packages/theme-default/src/index.css index ae46765b9..37c909a22 100644 --- a/packages/theme-default/src/index.css +++ b/packages/theme-default/src/index.css @@ -42,3 +42,4 @@ @import "./step.css"; @import "./carousel.css"; @import "./carousel-item.css"; +@import "./collapse.css"; diff --git a/src/index.js b/src/index.js index cafdacde1..e51b8dc4f 100644 --- a/src/index.js +++ b/src/index.js @@ -57,6 +57,8 @@ import Steps from '../packages/steps'; import Step from '../packages/step'; import Carousel from '../packages/carousel'; import CarouselItem from '../packages/carousel-item'; +import Collapse from '../packages/collapse'; +import CollapseItem from '../packages/collapse-item'; import locale from 'element-ui/src/locale'; const install = function(Vue, opts = {}) { @@ -117,6 +119,8 @@ const install = function(Vue, opts = {}) { Vue.component(Step.name, Step); Vue.component(Carousel.name, Carousel); Vue.component(CarouselItem.name, CarouselItem); + Vue.component(Collapse.name, Collapse); + Vue.component(CollapseItem.name, CollapseItem); Vue.use(Loading.directive); @@ -194,5 +198,7 @@ module.exports = { Steps, Step, Carousel, - CarouselItem + CarouselItem, + Collapse, + CollapseItem }; diff --git a/test/unit/specs/collapse.spec.js b/test/unit/specs/collapse.spec.js new file mode 100644 index 000000000..888dc8435 --- /dev/null +++ b/test/unit/specs/collapse.spec.js @@ -0,0 +1,96 @@ +import { createVue, destroyVM } from '../util'; + +describe('Collapse', () => { + let vm; + afterEach(() => { + destroyVM(vm); + }); + + it('create', done => { + vm = createVue({ + data() { + return { + activeNames: ['1'] + }; + }, + template: ` + + +
与现实生活一致:与现实生活的流程、逻辑保持一致,遵循用户习惯的语言和概念;
+
在界面中一致:所有的元素和结构需保持一致,比如:设计样式、图标和文本、元素的位置等。
+
+ +
控制反馈:通过界面样式和交互动效让用户可以清晰的感知自己的操作;
+
页面反馈:操作后,通过页面元素的变化清晰地展现当前状态。
+
+ +
简化流程:设计简洁直观的操作流程;
+
清晰明确:语言表达清晰且表意明确,让用户快速理解进而作出决策;
+
帮助用户识别:界面简单直白,让用户快速识别而非回忆,减少用户记忆负担。
+
+ +
用户决策:根据场景可给予用户操作建议或安全提示,但不能代替用户进行决策;
+
结果可控:用户可以自由的进行操作,包括撤销、回退和终止当前操作等。
+
+
+ ` + }, true); + const collapse = vm.$refs.collapse; + const spy = sinon.spy(); + + collapse.$on('change', spy); + expect(vm.$refs.item1.isActive).to.be.true; + vm.$refs.item3.$el.querySelector('.el-collapse-item__header').click(); + vm.$nextTick(_ => { + expect(vm.$refs.item1.isActive).to.be.true; + expect(vm.$refs.item3.isActive).to.be.true; + expect(spy.calledOnce).to.be.true; + + vm.$refs.item1.$el.querySelector('.el-collapse-item__header').click(); + + vm.$nextTick(_ => { + expect(vm.$refs.item1.isActive).to.be.false; + done(); + }); + }); + }); + + it('accordion', done => { + vm = createVue({ + data() { + return { + activeNames: ['1'] + }; + }, + template: ` + + +
与现实生活一致:与现实生活的流程、逻辑保持一致,遵循用户习惯的语言和概念;
+
在界面中一致:所有的元素和结构需保持一致,比如:设计样式、图标和文本、元素的位置等。
+
+ +
控制反馈:通过界面样式和交互动效让用户可以清晰的感知自己的操作;
+
页面反馈:操作后,通过页面元素的变化清晰地展现当前状态。
+
+ +
简化流程:设计简洁直观的操作流程;
+
清晰明确:语言表达清晰且表意明确,让用户快速理解进而作出决策;
+
帮助用户识别:界面简单直白,让用户快速识别而非回忆,减少用户记忆负担。
+
+ +
用户决策:根据场景可给予用户操作建议或安全提示,但不能代替用户进行决策;
+
结果可控:用户可以自由的进行操作,包括撤销、回退和终止当前操作等。
+
+
+ ` + }, true); + + expect(vm.$refs.item1.isActive).to.be.true; + vm.$refs.item3.$el.querySelector('.el-collapse-item__header').click(); + vm.$nextTick(_ => { + expect(vm.$refs.item1.isActive).to.be.false; + expect(vm.$refs.item3.isActive).to.be.true; + done(); + }); + }); +});