Skip to content

Instantly share code, notes, and snippets.

@Apexal
Created July 3, 2019 03:37
Show Gist options
  • Save Apexal/69a6780d89c2897b5dccc8633a9c2dc1 to your computer and use it in GitHub Desktop.
Save Apexal/69a6780d89c2897b5dccc8633a9c2dc1 to your computer and use it in GitHub Desktop.
My Svelte Todo App
<script>
/**
This is my first attempt at learning Svelte so I decided to try to make a simple todo list that saves to localStorage.
I was surprised by how few lines it took and how concise everything was, coming from a VueJS background.
I'm not sure of proper Svelte practices or conventions so things might not be ideal here but it seems to work well!
**/
import { onMount } from "svelte";
// Load items from localStorage
let items = JSON.parse(localStorage.getItem("items") || "[]");
// Fill test data
// for (let i = 0; i < 1000; i++)
// items = [...items, { text: `item ${i}`, completed: false }];
let newItemText = "";
function addItem() {
items = [...items, { text: newItemText, completed: false }];
newItemText = "";
}
// Automatically save to localStorage whenever items change
$: {
localStorage.setItem("items", JSON.stringify(items));
}
function scrollToTop() {
window.scrollTo({
top: 0,
behavior: "smooth"
});
}
</script>
<style>
h1 {
margin-bottom: 0.25em;
text-align: center;
}
h1 small {
color: rgb(194, 194, 194);
font-size: 0.6em;
}
form {
display: flex;
}
form input {
flex: 1;
}
.top-sticky {
position: sticky;
top: 0;
background-color: white;
padding-top: 1em;
}
.items {
padding-left: 0px;
list-style-type: none;
}
.item .item-text {
cursor: pointer;
}
.item.completed .item-text {
text-decoration: line-through;
}
.bottom-sticky {
position: sticky;
bottom: 0.5em;
}
</style>
<header class="top-sticky">
<h1>
Todo List
<small>{items.length} items</small>
</h1>
<form on:submit|preventDefault={addItem}>
<input
type="text"
placeholder="New todo item"
bind:value={newItemText}
required />
<button>Add</button>
</form>
</header>
<ul class="items">
{#each items as item, i (item)}
<li class="item" class:completed={item.completed}>
<input
class="item-completed"
type="checkbox"
bind:checked={item.completed} />
<span
class="item-text"
on:click={e => (item.completed = !item.completed)}>
{item.text}
</span>
</li>
{/each}
</ul>
{#if items.length > 0}
<footer class="bottom-sticky">
<button on:click={e => (items = [])}>Clear</button>
<button style="float: right" on:click={scrollToTop}>Back to Top</button>
</footer>
{/if}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment