Created
July 3, 2019 03:37
-
-
Save Apexal/69a6780d89c2897b5dccc8633a9c2dc1 to your computer and use it in GitHub Desktop.
My Svelte Todo App
This file contains 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
<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