JSFiddle - React, Tailwind, and code Playground
by Kye Hohenberger
HTML
<script src="https://unpkg.com/preact/dist/preact.min.js"></script>
<script src="https://unpkg.com/proptypes"></script>
<script src="https://unpkg.com/preact-compat/dist/preact-compat.min.js"></script>
<script src="https://cdn.rawgit.com/developit/0c2755a85948cb62e663170e403c9697/raw/9591812d5742f25e2df6b90133ccc70ba2241485/preact-polyfill.js"></script>
<script src="https://unpkg.com/[email protected]/umd/data-driven-motion.min.js"></script>
<script src="https://unpkg.com/[email protected]/dist/preact-scroll-viewport.min.js"></script>
<script src="https://cdn.pubnub.com/sdk/javascript/pubnub.4.4.4.min.js"></script>
CSS
html, body {
background: #EEE;
margin: 0;
font: 16px/1.3 'Helvetica Neue', helvetica, arial, sans-serif;
color: #000;
width: 100%;
height: 100%;
}
.count {
position: fixed;
right: 0;
top: 0;
padding: 10px;
background: #000;
color: #FFF;
z-index: 100;
}
.item {
position: relative;
box-sizing: border-box;
padding: 10px;
width: 100%;
height: 90px;
background: #FFF;
border-bottom: 1px solid #DDD;
overflow: hidden;
contain: strict;
}
.avatar {
float: left;
margin: 0 10px 0 0;
width: 48px;
height: 48px;
img {
width: 48px;
height: 48px;
border-radius: 3px;
}
}
.author-name {
color: #555;
text-decoration: none;
font-weight: bold;
}
.author-screenname {
color: #AAA;
margin-left: 1em;
text-decoration: none;
font-size: 80%;
}
.text {
margin: 0;
padding: 0;
overflow: hidden;
}
Babel + JSX
const { h, Component, render } = preact
/** @jsx h */
const { Motion } = DDM // https://github.com/tkh44/data-driven-motion
const WOBBLY_SPRING = { stiffness: 280, damping: 30 }
/** Demo: Stream twitter firehose into
* a naive VDOM list with shouldComponentUpdate.
*/
class Demo extends Component {
state = {
messages: []
}
handleMessage = msg => {
// we'll mutate in-place to save some copy ops
// TIP: you can store VDOM in state!
// Avoids constantly re-mapping data -> VDOM in render.
// this.state.messages.push(
// <Message id={msg.message.id_str} message={msg.message} />
// );
this.state.messages = [...this.state.messages.slice(-4), msg]
// just trigger a state update
this.setState()
}
componentDidMount () {
let stream = new PubNub({
subscribeKey: 'sub-c-78806dd4-42a6-11e4-aed8-02ee2ddab7fe'
})
stream.addListener({
message: this.handleMessage
})
stream.subscribe({
channels: ['pubnub-twitter']
})
}
render ({}, { messages }) {
return (
<div class="list" style={{ width: '100%', height: '100%' }}>
<span class="count">{messages.length} tweets ({messages.length * 9} elements)</span>
<Motion
data={this.state.messages.slice(-5)}
component={(<div overscan={20} style={{ width: '100%', height: '100%' }} />)}
getKey={(msg, i) => i + ''}
onComponentMount={() => ({ y: 0 })}
onRender={(data, i, spring) => {
return ({
y: spring(i * 90, WOBBLY_SPRING)
})
}}
onRemount={(data, i) => ({ y: 200 })}
onUnmount={(data, spring) => ({ y: spring(90) })}
render={(key, msg, style, dataIndex) => {
return (
<Message
key={key}
id={msg.message.id_str}
message={msg.message}
style={{
position: 'absolute',
top: 0,
...