Todo App • HTM + Preact + WindiCSS
Basic todo app example in < 100 lines of code with HTM + Preact + WindiCSS.
by Nicholas Berlette
HTML
<link rel="stylesheet" href="https://unpkg.com/@typehaus/metropolis/100.css">
<link rel="stylesheet" href="https://unpkg.com/@typehaus/metropolis/500.css">
<link rel="stylesheet" href="https://unpkg.com/@typehaus/metropolis/900.css">
<link rel="stylesheet" href="https://unpkg.com/@typehaus/metropolis/700.css">
<div id="app" class="wrapper !opacity-100">
<noscript>Please enable JavaScript to use this app.</noscript>
</div>
<script type="module">
import { html, Component, render } from 'https://unpkg.com/[email protected]/preact/standalone.module.js';
var $ = document.querySelector.bind(document);
var $$ = document.querySelectorAll.bind(document);
class App extends Component {
addTodo(input) {
const { todos = [] } = this.state;
const text = input.value.trim();
this.setState({ todos: todos.concat(text.length > 0 ? text : `item number ${(todos.length + 1)}`) });
input.value = '';
}
render({ name = 'Todo List', page = 'today' }, state) {
return html`
<div class="app top-rainbow group ${page}">
<${Header} name="${name || 'Todo'}" page="${page}" />
<div class="px-2">
<${List}>
${(this.state.todos??=[]).map((todo, index) => html`<${Todo} key=${todo + index} id=${`todo-${index}`}>${todo}</li>`)}
<//>
<${Input} placeholder="type a todo and press enter to add" onKeyPress=${(e) => (e.keyCode === 13) && this.addTodo($(`.${page} .input-text`))}/>
</div>
</div>
`;
}
}
const Header = ({ name, page = 'all' }) => html`<h1 class="h1"><span class="title">${name}</span><span class="page group-hover:!opacity-80">${page}</span></h1>`
const List = props => html`<ul class="todo-list" ...${props} />`
const Input = props => html`<input type="text" class="input-text" ...${props} />`
const Button = props => html`<button class="btn btn-blue text-xs ease-colors" ...${props} />`
const Link = ({ to, text, ...props }) => html`<a href="${to}" title="${text}" class="link" ${to.startsWith('http') ? 'target="_blank"...
CSS
* {
font-family: 'Metropolis', sans-serif !important;
}
#app {
transition: 1.5s opacity 1s ease-in;
opacity: 0;
}