JSFiddle - React, Tailwind, and code Playground
by Derek Wood
HTML
<header class="page-section site-header">
<div class="inner-w">
<p>Just a way to have that ol column... so, you see that it's not integral to the below</p>
</div>
</header>
<section class="page-section section-name">
<div class="inner-w">
<aside class="component-name">
<ul class="list" id="exampleTarget">
<!-- it's likely - that this will be dynamically populated - by PHP or AJAX or - if you're lucky, Emberjs -->
<!--
<li class="item">
<aside class="card">
<button class="remove-card">
x
</button>
<span>{{id}}</span>
</aside>
</li>
-->
</ul>
<footer>
<button data-trigger='add-card'>
<span>Add a card</span>
</button>
</footer>
</aside>
</div>
</section>
CSS
/* READ IT: https://www.paulirish.com/2012/box-sizing-border-box-ftw/ */
/* apply a natural box layout model to all elements, but allowing components to change */
html {
box-sizing: border-box;
}
*, *:before, *:after {
box-sizing: inherit;
}
/* Keep in mind that I added normalize CSS to kinda 'reset' the crappy CSS defaults */
.page-section .inner-w {
width: 100%; /* let it be as big as it can */
max-width: 900px; /* not too big though */
margin-right: auto;
margin-left: auto;
padding: 1rem;
border: 1px solid gray;
}
.site-header {
background: darkgray;
color: white;
}
.site-header p {
opacity: .3;
}
/* ..... */
.component-name {
background: lightgray;
}
.component-name .list {
display: flex;
flex-direction: row;
justify-content: space-around;
align-items: center;
padding: 1rem;
}
.component-name .item {
/* ... */
}
.component-name .card {
position: relative; /* for the remove button */
padding: 2rem 4rem;
background: #56B9C6;
border-radius: .5rem;
color: white;
}
.component-name footer {
display: flex;
justify-content: center;
margin-top: 3rem;
}
.component-name button.remove-card {
position: absolute;
top: 0;
right: 0;
opacity: .4;
}
JavaScript
console.clear();
var idMaker = { // there are better ways to do this... but for fun ->
ids: [],
removed: [], // you could save the ones you remove
latestId: 0,
create: function() {
this.latestId = this.latestId + 1;
this.ids.push(this.latestId);
console.log('ID #' + this.latestId + ' created');
this.read();
return this.latestId;
},
read: function() {
console.clear();
console.log('created: ', this.ids);
console.log('removed: ', this.removed);
},
}; // creates a little library for creating id's for the cards
idMaker.read(); // no ids to start
// will take an object with the list name and the card id
// eventuallly - you'd want the card to have more info sent in...
function addCard(infoObject) {
var targetList = document.getElementById(infoObject.list);
var li = document.createElement('li');
li.classList.add('item');
var component = document.createElement('aside');
component.classList.add('card');
var title = document.createElement('h2');
var uniqueId = idMaker.create();
var id = document.createTextNode(uniqueId);
title.appendChild(id);
component.appendChild(title)
li.appendChild(component);
targetList.appendChild(li);
// woah... this part is really boring...
// this is why templating engines and JSON are so popular
// you could also add 'remove' button etc... right?
var removeButton = document.createElement('button');
var removeText = document.createTextNode('x');
removeButton.appendChild(removeText);
removeButton.classList.add('remove-card');
component.appendChild(removeButton);
//
removeButton.addEventListener('click', function() {
var parent = document.getElementById(infoObject.list);
idMaker.removed.push(uniqueId);
parent.removeChild(li);
idMaker.read();
});
}
// start out with a few?
addCard({list: 'exampleTarget'});
addCard({list: 'exampleTarget'});
addCard({list: 'exampleTarget'});
// start a UI to add cards
var addCardButton =...