Last active
January 25, 2018 19:28
-
-
Save jfbrennan/8fd5c0272660cad4e2d23e93863983ea to your computer and use it in GitHub Desktop.
Alert UI component rebuilt to compare Riot vs Slim vs Polymer vs Vue vs React and more
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<dom-module id="poly-alert"> | |
<template> | |
<div> | |
<i id="icon"></i> | |
<div> | |
<h6 dom-if="title" class="alert-title sub-header">{{title}}</h6> | |
<p>{{msg}}</p> | |
</div> | |
<button dom-if="!preventClose" id="dismissBtn" class="btn-close alert-remove"><span class="icon icon-close"></span></button> | |
</div> | |
</template> | |
<script> | |
class PolyAlert extends Polymer.Element { | |
static get is() { return 'poly-alert'; } | |
static get properties() { | |
return { | |
type: String, | |
title: String, | |
msg: String, | |
autodismiss: Object, | |
preventClose: { | |
type: Boolean, | |
value: false | |
} | |
}; | |
} | |
constructor() { | |
super(); | |
} | |
ready() { | |
super.ready(); | |
// Create class lists | |
this.shadowRoot.firstElementChild.classList.add('alert'); | |
this.shadowRoot.firstElementChild.classList.add('alert-' + this.type); | |
this.$.icon.classList.add('icon'); | |
this.$.icon.classList.add('icon-' + (this.type === 'success' ? 'check' : this.type === 'error' ? 'info' : 'warn') + 'alt'); | |
// on-click approach means the callback's context is the target not this element | |
this.$.dismissBtn.addEventListener('click', this.dismiss.bind(this)); | |
if (this.autodismiss) { | |
var seconds = (typeof this.autodismiss === 'number' ? this.autodismiss : 4) * 1000; | |
setTimeout(this.close.bind(this), seconds); | |
} | |
} | |
// Removes Alert after CSS transition finishes. Publishes UITK event. | |
dismiss(e) { | |
var element = this.shadowRoot.firstElementChild; // firstElementChild is hacky, no find('.alert')??? | |
this.addEventListener('transitionend', function(e) { | |
this.remove(); | |
uitk.publish('alert.remove', this); | |
}.bind(this), {once: true}); | |
element.classList.add('remove-animated'); // IE11 can't take multiple args :( | |
element.classList.add('animated-fade'); // IE11 can't take multiple args :( | |
} | |
} | |
customElements.define(PolyAlert.is, PolyAlert); | |
</script> | |
<style> | |
// Shadow DOM! Will have to redo all the existing Alert styles and any helpers like animation classes | |
// Would be ~100 more loc | |
</style> | |
</dom-module> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, {Component} from 'react' | |
import PropTypes from 'prop-types' | |
class ReactAlert extends Component { | |
static defaultProps = { | |
icon: null, | |
msg: '', | |
type: 'info', | |
autodismiss: 0, | |
onRemoveAlert: () => {} | |
}; | |
static propTypes = { | |
icon: PropTypes.element, | |
msg: PropTypes.PropTypes.string, | |
type: PropTypes.oneOf(['info', 'success', 'error', 'warn']), | |
autodismiss: PropTypes.oneOfType([ | |
PropTypes.number, | |
PropTypes.boolean | |
]), | |
onRemoveAlert: PropTypes.func | |
}; | |
_removeItself = () => { | |
const {onRemoveAlert, id} = this.props; | |
onRemoveAlert(id) | |
}; | |
componentDidMount () { | |
const {autodismiss} = this.props; | |
if (autodismiss) { | |
let seconds = (typeof autodismiss === 'number' ? autodismiss : 4) * 1000; | |
setTimeout(() => { this._removeItself() }, seconds) | |
} | |
} | |
render () { | |
const {msg, icon, type} = this.props; | |
return ( | |
<div> | |
<div className={alert alert-{type}> | |
<i className={icon icon-{icon}></i> | |
<div> | |
<h6 className="alert-title sub-header">{title}</h6> | |
<p>{msg}</p> | |
</div> | |
<button onClick={this._removeItself} className="btn-close alert-remove"></button> | |
</div> | |
</div> | |
) | |
} | |
} | |
export default ReactAlert |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<riot-alert class="alert alert-{opts.type} {remove-animated: removing, animated-fade: removing}"> | |
<i class="icon icon-{icon}alt"></i> | |
<div> | |
<h6 if="{opts.title}" class="alert-title sub-header">{opts.title}</h6> | |
<p>{opts.msg}</p> | |
</div> | |
<button if="{!opts.preventclose}" onclick="{dismiss}" class="btn-close alert-remove"><span class="icon icon-close"></span></button> | |
<script> | |
// Determine Icon based on type | |
this.icon = this.opts.type === 'success' ? 'check' : this.opts.type === 'error' ? 'info' : 'warn'; | |
// Removes Alert after CSS transition finishes. Publishes UITK event. | |
dismiss(e) { | |
this.root.addEventListener('transitionend', function(e) { | |
this.unmount(); | |
uitk.publish('alert.remove'); | |
}.bind(this), {once: true}); | |
this.removing = true; // Transition event callback will do the unmount | |
} | |
this.on('mount', function() { | |
if (this.opts.autodismiss) { | |
var seconds = (typeof this.opts.autodismiss === 'number' ? this.opts.autodismiss : 4) * 1000; | |
setTimeout(this.remove.bind(this), seconds); | |
} | |
}) | |
</script> | |
</riot-alert> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Slim.tag('slim-alert', | |
` | |
<div bind:class="alertClass"> | |
<i bind:class="iconClass"></i> | |
<div> | |
<h6 s:if="title" class="alert-title sub-header" bind>{{title}}</h6> | |
<p bind>{{msg}}</p> | |
</div> | |
<button s:if="!preventClose" click="dismiss" class="btn-close alert-remove"><span class="icon icon-close"></span></button> | |
</div> | |
`, | |
class SlimAlert extends Slim { | |
onBeforeCreated() { | |
this.type = this.getAttribute('type'); | |
this.msg = this.getAttribute('msg') || ''; | |
this.preventClose = this.hasAttribute('preventclose'); | |
this.autodismiss = this.getAttribute('dismiss'); | |
// Create class lists | |
this.alertClass = 'alert alert-' + this.type; | |
this.iconClass = 'icon icon-' + (this.type === 'success' ? 'check' : this.type === 'error' ? 'info' : 'warn') + 'alt'; | |
// Removes SlimAlert after CSS transition finishes. Publishes UITK event. | |
this.dismiss = function() { | |
this.addEventListener('transitionend', (e) => { | |
this.remove(); | |
uitk.publish('alert.remove'); | |
}, {once: true}); | |
this.find('.alert').classList.add('remove-animated'); // IE11 can't take multiple args :( | |
this.find('.alert').classList.add('animated-fade'); // IE11 can't take multiple args :( | |
} | |
} | |
onCreated() { | |
if (this.autodismiss) { | |
var seconds = (typeof this.autodismiss === 'number' ? this.autodismiss : 4) * 1000; // The given secs or default to 4 secs | |
setTimeout(this.unmount.bind(this), seconds); | |
} | |
} | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Vue.component('vue-alert', {template: | |
`<div v-bind:class="'alert alert-' + type"> | |
<i v-bind:class="'icon icon-' + icon"></i> | |
<div> | |
<h6 v-if="title" class="alert-title sub-header">{{title}}</h6> | |
<p>{{msg}}</p> | |
</div> | |
<button v-if="preventClose" v-on:click="dismiss" class="btn-close alert-remove"><span class="icon icon-close"></span></button> | |
</div> | |
`, | |
props: ['type', 'title', 'msg', 'autodismiss', 'preventClose'], | |
data: function () { | |
return { | |
counter: 0 | |
} | |
}, | |
computed: { | |
icon: function () { | |
return this.type === 'success' ? 'check' : this.type === 'error' ? 'info' : 'warn' | |
} | |
}, | |
methods: { | |
dismiss: function() { | |
this.root.addEventListener('transitionend', function(e) { | |
this.unmount(); | |
uitk.publish('alert.remove'); | |
}.bind(this), {once: true}); | |
this.removing = true; // Transition event callback will do the unmount | |
} | |
} | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
The above components implement the same requirements. These are:
type
(one ofinfo
,success
,warn
, orerror
; determines colors)title
message
autodismiss
(passtrue
for the default duration, or passNumber
of seconds for custom duration)disabled
(set it to hide the dismiss button)