From 8f5a84ceecee85ed516b072c359642713f8fce4a Mon Sep 17 00:00:00 2001 From: chenjiahan Date: Mon, 16 Nov 2020 20:49:46 +0800 Subject: [PATCH] feat: add popover component --- src/popover/README.md | 32 ++++++++ src/popover/README.zh-CN.md | 66 ++++++++++++++++ src/popover/demo/index.vue | 60 +++++++++++++++ src/popover/index.js | 76 +++++++++++++++++++ src/popover/index.less | 61 +++++++++++++++ .../test/__snapshots__/demo.spec.js.snap | 58 ++++++++++++++ .../test/__snapshots__/index.spec.js.snap | 22 ++++++ src/popover/test/demo.spec.js | 4 + src/popover/test/index.spec.js | 2 + vant.config.js | 8 ++ 10 files changed, 389 insertions(+) create mode 100644 src/popover/README.md create mode 100644 src/popover/README.zh-CN.md create mode 100644 src/popover/demo/index.vue create mode 100644 src/popover/index.js create mode 100644 src/popover/index.less create mode 100644 src/popover/test/__snapshots__/demo.spec.js.snap create mode 100644 src/popover/test/__snapshots__/index.spec.js.snap create mode 100644 src/popover/test/demo.spec.js create mode 100644 src/popover/test/index.spec.js diff --git a/src/popover/README.md b/src/popover/README.md new file mode 100644 index 000000000..5772a8d1b --- /dev/null +++ b/src/popover/README.md @@ -0,0 +1,32 @@ +# Popover + +### Install + +```js +import Vue from 'vue'; +import { Popover } from 'vant'; + +Vue.use(Popover); +``` + +## Usage + +### Basic Usage + +```html + +``` + +## API + +### Props + +| Attribute | Description | Type | Default | +| --------- | ----------- | ---- | ------- | + + +### Events + +| Event | Description | Arguments | +| ----- | ----------- | --------- | + diff --git a/src/popover/README.zh-CN.md b/src/popover/README.zh-CN.md new file mode 100644 index 000000000..e67674d25 --- /dev/null +++ b/src/popover/README.zh-CN.md @@ -0,0 +1,66 @@ +# Popover 气泡弹出框 + +### 介绍 + +### 引入 + +```js +import Vue from 'vue'; +import { Popover } from 'vant'; + +Vue.use(Popover); +``` + +## 代码演示 + +### 基础用法 + +```html + +``` + +## API + +### Props + +| 参数 | 说明 | 类型 | 默认值 | +| --- | --- | --- | --- | +| v-model | 是否展示气泡弹出层 | _boolean_ | `false` | +| actions | 选项列表 | _Action[]_ | `[]` | +| placement | 弹出位置 | _string_ | - | +| theme | 主题风格,可选值为 `light` | _string_ | `dark` | +| text-color | 自定义文字颜色 | _string_ | - | +| background-color | 自定义背景颜色 | _string_ | - | +| overlay | 是否显示遮罩层 | _boolean_ | `false` | +| close-on-click-action | 是否在点击选项后关闭 | _boolean_ | `false` | +| close-on-click-outside | 是否在点击外部元素后关闭菜单 | _boolean_ | `true` | +| get-container `v2.4.4` | 指定挂载的节点,[用法示例](#/zh-CN/popup#zhi-ding-gua-zai-wei-zhi) | _string \| () => Element_ | - | + +### Action 数据结构 + +`actions` 属性是一个由对象构成的数组,数组中的每个对象配置一列,对象可以包含以下值: + +| 键名 | 说明 | 类型 | +| --------- | ------------------------ | -------- | +| text | 文字内容 | _string_ | +| className | 为对应选项添加额外的类名 | _any_ | + +### placement 可选值 + +top left right bottom topLeft topRight bottomLeft bottomRight leftTop leftBottom rightTop rightBottom + +### Events + +| 事件名 | 说明 | 回调参数 | +| ------ | ------------------------ | ------------------------------- | +| select | 点击选项时触发 | _action: Action, index: number_ | +| open | 打开菜单时触发 | - | +| close | 关闭菜单时触发 | - | +| opened | 打开菜单且动画结束后触发 | - | +| closed | 关闭菜单且动画结束后触发 | - | + +### Slots + +| 名称 | 说明 | +| ------- | -------------------- | +| default | 自定义菜单的展示内容 | diff --git a/src/popover/demo/index.vue b/src/popover/demo/index.vue new file mode 100644 index 000000000..98940a1db --- /dev/null +++ b/src/popover/demo/index.vue @@ -0,0 +1,60 @@ + + + + + diff --git a/src/popover/index.js b/src/popover/index.js new file mode 100644 index 000000000..93b722a53 --- /dev/null +++ b/src/popover/index.js @@ -0,0 +1,76 @@ +import { createNamespace } from '../utils'; + +// Mixins +import { ClickOutsideMixin } from '../mixins/click-outside'; + +// Components +import Popup from '../popup'; + +const [createComponent, bem] = createNamespace('popover'); + +export default createComponent({ + mixins: [ + ClickOutsideMixin({ + event: 'click', + method: 'onClickOutside', + }), + ], + + props: { + value: Boolean, + overlay: Boolean, + placement: String, + textColor: String, + getContainer: [String, Function], + backgroundColor: String, + closeOnClickAction: Boolean, + theme: { + type: String, + default: 'dark', + }, + actions: { + type: Array, + default: () => [], + }, + }, + + methods: { + renderAction(action) { + return
{action.text}
; + }, + + onToggle(value) { + this.$emit('input', value); + }, + + onClickAction(action, index) { + this.$emit('select', action, index); + + if (this.closeOnClickAction) { + this.$emit('input', false); + } + }, + + onClickOutside() { + this.$emit('input', false); + }, + }, + + render() { + return ( + + + {this.actions.map(this.renderAction)} + + {this.slots('default')} + + ); + }, +}); diff --git a/src/popover/index.less b/src/popover/index.less new file mode 100644 index 000000000..a51896139 --- /dev/null +++ b/src/popover/index.less @@ -0,0 +1,61 @@ +@import '../style/var'; +@import '../style/mixins/hairline'; + +.van-popover { + position: absolute; + border-radius: @border-radius-lg; + transform: none; + transition: all 0.3s; + + &__action { + position: relative; + display: flex; + align-items: center; + justify-content: center; + width: 128px; + height: 44px; + font-size: @font-size-md; + + &::after { + .hairline-bottom(@cell-border-color, @padding-md, @padding-md); + } + + &:last-child::after { + display: none; + } + } + + &--light { + color: @text-color; + background-color: @white; + box-shadow: 0 2px 12px rgba(50, 50, 51, 0.12); + + .van-popover__action { + &:active { + background-color: @active-color; + } + } + } + + &--dark { + color: @white; + background-color: @gray-8; + opacity: 0.9; + + .van-popover__action { + &::after { + border-color: @gray-7; + } + + &:active { + opacity: @active-opacity; + } + } + } + + &-zoom-enter, + &-zoom-leave-active { + transform: scale(0.8); + opacity: 0; + } +} diff --git a/src/popover/test/__snapshots__/demo.spec.js.snap b/src/popover/test/__snapshots__/demo.spec.js.snap new file mode 100644 index 000000000..7c04f9b40 --- /dev/null +++ b/src/popover/test/__snapshots__/demo.spec.js.snap @@ -0,0 +1,58 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`renders demo correctly 1`] = ` +
+
+
+
span: 8
+
span: 8
+
span: 8
+
+
+
span: 4
+
+ offset: 4, span: 10 +
+
+
+
+ offset: 12, span: 12 +
+
+
+
+
+
span: 8
+
span: 8
+
span: 8
+
+
+
+
+
span: 6
+
span: 6
+
span: 6
+
+
+
span: 6
+
span: 6
+
span: 6
+
+
+
span: 6
+
span: 6
+
span: 6
+
+
+
span: 6
+
span: 6
+
span: 6
+
+
+
span: 6
+
span: 6
+
span: 6
+
+
+
+`; diff --git a/src/popover/test/__snapshots__/index.spec.js.snap b/src/popover/test/__snapshots__/index.spec.js.snap new file mode 100644 index 000000000..2d4588095 --- /dev/null +++ b/src/popover/test/__snapshots__/index.spec.js.snap @@ -0,0 +1,22 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`gutter prop 1`] = ` +
+
24
+
12
+
12
+
8
+
8
+
8
+
6
+
6
+
6
+
6
+
7
+
6
+
5
+
4
+
3
+
2
+
+`; diff --git a/src/popover/test/demo.spec.js b/src/popover/test/demo.spec.js new file mode 100644 index 000000000..5c70922b5 --- /dev/null +++ b/src/popover/test/demo.spec.js @@ -0,0 +1,4 @@ +import Demo from '../demo'; +import { snapshotDemo } from '../../../test/demo'; + +snapshotDemo(Demo); diff --git a/src/popover/test/index.spec.js b/src/popover/test/index.spec.js new file mode 100644 index 000000000..0ccd98fb1 --- /dev/null +++ b/src/popover/test/index.spec.js @@ -0,0 +1,2 @@ +// import Popover from '..'; +// import { mount } from '../../../test'; diff --git a/vant.config.js b/vant.config.js index d025939c2..d7c9046dc 100644 --- a/vant.config.js +++ b/vant.config.js @@ -275,6 +275,10 @@ module.exports = { path: 'notice-bar', title: 'NoticeBar 通知栏', }, + { + path: 'popover', + title: 'Popover 气泡弹出框', + }, { path: 'progress', title: 'Progress 进度条', @@ -638,6 +642,10 @@ module.exports = { path: 'notice-bar', title: 'NoticeBar', }, + { + path: 'popover', + title: 'Popover', + }, { path: 'progress', title: 'Progress',