Skip to content

Commit

Permalink
Merge f46cb8e into a24d340
Browse files Browse the repository at this point in the history
  • Loading branch information
wxsms committed Nov 18, 2017
2 parents a24d340 + f46cb8e commit f6de5db
Show file tree
Hide file tree
Showing 7 changed files with 699 additions and 0 deletions.
191 changes: 191 additions & 0 deletions docs/pages/components/Notification.md
@@ -0,0 +1,191 @@
# Notification

> Displays a global notification message at a corner of the page.
## Example

Click on the button below to show a notification. By default, it is dismissible with a close button, and will dismiss automatically after 5000ms (both are configurable).

```html
<template>
<section>
<btn @click="notify" type="primary">Default Notification</btn>
<btn @click="notify2" type="primary">No Auto-dismiss Notification</btn>
</section>
</template>
<script>
export default {
methods: {
// example with callback
notify () {
this.$notify({
title: 'Title',
content: 'This is a notify message.'
}, () => {
// callback after dismissed
console.log('dismissed')
})
},
// example with Promise
notify2 () {
this.$notify({
title: 'Title',
content: 'This notification will not dismiss automatically.',
duration: 0
}).then(() => {
// resolve after dismissed
console.log('dismissed')
})
}
}
}
</script>
<!-- notification-example.vue -->
```

## Types

There're 4 optional types of notification: `info` / `success` / `warning` / `danger`.

Notification with specific type will has a default icon on the left, you can also change or remove the icon by `icon` option.

```html
<template>
<section>
<btn @click="info" type="info">Info</btn>
<btn @click="success" type="success">Success</btn>
<btn @click="warning" type="warning">Warning</btn>
<btn @click="danger" type="danger">Danger</btn>
</section>
</template>
<script>
export default {
methods: {
info () {
this.$notify({
type: 'info',
title: 'Heads up!',
content: 'This alert needs your attention, but it\'s not super important.'
})
},
success () {
this.$notify({
type: 'success',
title: 'Well done!',
content: 'You successfully read this important alert message.'
})
},
warning () {
this.$notify({
type: 'warning',
title: 'Warning!',
content: 'Better check yourself, you\'re not looking too good.'
})
},
danger () {
this.$notify({
type: 'danger',
title: 'Oh snap!',
content: 'Change a few things up and try submitting again.'
})
}
}
}
</script>
<!-- notification-types.vue -->
```

## Placements

Notifications can be placed on any corner on a page.

The `position` prop defines which corner a notification will slide in. It can be `top-right` (default), `top-left`, `bottom-right` or `bottom-left`.

```html
<template>
<section>
<btn @click="notify('top-right')" type="primary">Top Right (Default)</btn>
<btn @click="notify('bottom-right')" type="primary">Bottom Right</btn>
<btn @click="notify('bottom-left')" type="primary">Bottom Left</btn>
<btn @click="notify('top-left')" type="primary">Top Left</btn>
</section>
</template>
<script>
export default {
methods: {
notify (placement) {
this.$notify({
placement, // equal to `placement: placement` in ES6
title: 'Title',
content: `This is a notify msg at ${placement}.`
})
}
}
}
</script>
<!-- notification-placements.vue -->
```

## Dismissible

By default a notification is dismissible with a close button, you can hide it by setting `dismissible` to `false`.

```html
<template>
<btn @click="notify" type="primary">Notification Without Dismiss Button</btn>
</template>
<script>
export default {
methods: {
notify () {
this.$notify({
title: 'Title',
content: 'This is a notification without dismiss btn.',
dismissible: false
})
}
}
}
</script>
<!-- notification-without-dismiss-btn.vue -->
```

## Global Method

`$notify(options, callback)` global method for `Vue.prototype` will be added **if uiv is installed**.

Note that the dismissed callback is optional.

The method will return a `Promise` object that resolve while the notification is dismissed (if supported by browser or with es6 promise polyfill).

## Import Individually

If you prefer importing `Notification` individually:

```javascript
import { Notification } from 'uiv'
```

The corresponding method is `Notification.notify`, with same parameters as above.

# API Reference

## [Notification.vue](https://github.com/wxsms/uiv/tree/master/src/services/notification/Notification.vue)

These props are used as `options` in the methods above.

### Props

Name | Type | Default | Required | Description
---------- | ---------- | -------- | -------- | -----------------------
`title` | String | | | The notification title.
`content` | String | | | The notification content.
`type` | String | | | Support: `info` / `success` / `warning` / `danger`.
`duration` | Number | 5000 | | Dismiss after milliseconds, use 0 to prevent self-closing.
`dismissible` | Boolean | true | | Show dismiss button.
`placement` | String | top-right | | Support: `top-right` / `top-left` / `bottom-right` / `bottom-left`.
`icon` | String | | | Custom icon class, use an empty string to disable icon.

## [notification.js](https://github.com/wxsms/uiv/tree/master/src/services/notification/notification.js)

This file has no props.
5 changes: 5 additions & 0 deletions docs/router/routes.js
Expand Up @@ -71,6 +71,11 @@ const routes = [
meta: {type: 'component', label: 'Modal'},
component: () => import('./../pages/components/Modal.md')
},
{
path: '/notification',
meta: {type: 'component', label: 'Notification'},
component: () => import('./../pages/components/Notification.md')
},
{
path: '/pagination',
meta: {type: 'component', label: 'Pagination'},
Expand Down
1 change: 1 addition & 0 deletions src/services/index.js
@@ -1 +1,2 @@
export {default as MessageBox} from './messagebox/messageBox.js'
export {default as Notification} from './notification/notification.js'
123 changes: 123 additions & 0 deletions src/services/notification/Notification.vue
@@ -0,0 +1,123 @@
<template>
<alert
class="fade"
:style="styles"
:type="type"
:duration="duration"
:dismissible="dismissible"
@dismissed="onDismissed">
<div class="media" style="margin: 0">
<div class="media-left" v-if="icons">
<span :class="icons" style="font-size: 1.5em"></span>
</div>
<div class="media-body">
<h4 class="media-heading">{{title}}</h4>
<div>{{content}}</div>
</div>
</div>
</alert>
</template>

<script>
import {addClass, removeClass} from '@src/utils/domUtils'
import {isString} from '@src/utils/objectUtils'
import Alert from '@src/components/alert/Alert.vue'
import {TYPES, PLACEMENTS} from './constants'
const IN_CLASS = 'in'
const ICON = 'glyphicon'
const OFFSET = 15
const WIDTH = 300
const TRANSITION_DURATION = 300
const getTotalHeightOfQueue = (queue, lastIndex = queue.length) => {
let totalHeight = OFFSET
for (let i = 0; i < lastIndex; i++) {
totalHeight += queue[i].height + OFFSET
}
return totalHeight
}
export default {
components: {Alert},
props: {
title: String,
content: String,
duration: {
type: Number,
default: 5000
},
dismissible: {
type: Boolean,
default: true
},
type: String,
placement: String,
icon: String,
cb: {
type: Function,
required: true
},
queue: {
type: Array,
required: true
}
},
data () {
return {
height: 0,
top: 0,
horizontal: this.placement === PLACEMENTS.TOP_LEFT || this.placement === PLACEMENTS.BOTTOM_LEFT ? 'left' : 'right',
vertical: this.placement === PLACEMENTS.TOP_LEFT || this.placement === PLACEMENTS.TOP_RIGHT ? 'top' : 'bottom'
}
},
created () {
// get prev notifications total height in the queue
this.top = getTotalHeightOfQueue(this.queue)
},
mounted () {
const el = this.$el
el.style[this.vertical] = this.top + 'px'
this.$nextTick(() => {
el.style[this.horizontal] = `-${WIDTH}px`
this.height = el.offsetHeight
el.style[this.horizontal] = `${OFFSET}px`
addClass(el, IN_CLASS)
})
},
computed: {
styles () {
let queue = this.queue
let thisIndex = queue.indexOf(this)
return {
position: 'fixed',
[this.vertical]: `${getTotalHeightOfQueue(queue, thisIndex)}px`,
width: `${WIDTH}px`,
transition: `all ${TRANSITION_DURATION / 1000}s ease-in-out`
}
},
icons () {
if (isString(this.icon)) {
return this.icon
}
switch (this.type) {
case TYPES.INFO:
case TYPES.WARNING:
return `${ICON} ${ICON}-info-sign`
case TYPES.SUCCESS:
return `${ICON} ${ICON}-ok-sign`
case TYPES.DANGER:
return `${ICON} ${ICON}-remove-sign`
default:
return null
}
}
},
methods: {
onDismissed () {
removeClass(this.$el, IN_CLASS)
setTimeout(this.cb, TRANSITION_DURATION)
}
}
}
</script>
13 changes: 13 additions & 0 deletions src/services/notification/constants.js
@@ -0,0 +1,13 @@
export const TYPES = {
SUCCESS: 'success',
INFO: 'info',
DANGER: 'danger',
WARNING: 'warning'
}

export const PLACEMENTS = {
TOP_LEFT: 'top-left',
TOP_RIGHT: 'top-right',
BOTTOM_LEFT: 'bottom-left',
BOTTOM_RIGHT: 'bottom-right'
}

0 comments on commit f6de5db

Please sign in to comment.