improve actions, add dark mode

This commit is contained in:
Jonathan Jenne 2022-06-13 22:27:35 +02:00
parent 3d6f0d2f01
commit f4e80302dc
5 changed files with 175 additions and 44 deletions

View File

@ -1,6 +1,8 @@
<script>
import MainInput from './lib/MainInput.svelte'
import Note from './lib/Note.svelte'
import Actions from './lib/Actions.svelte'
import Storage from './storage'
import {createNote, toggleDoneState} from './note'
@ -8,7 +10,15 @@
let notes = storage.getNotes()
let shownNotes = notes
let hasNotes = notes.length > 0
let clearConfirm = false
let filter = null
let theme = storage.getTheme()
$: hasFinishedNotes = notes.filter(note => !note.done).length === notes.length
$: darkMode = theme === "dark"
$: document.body.className = theme;
// $: filterText = filter ? `Clear '${filter}' filter` : "Clear filter"
// $: hasFinishedNotes = notes.filter(note => !note.done).length === notes.length
function handleNewNote(e) {
notes.push(createNote(e.detail))
@ -26,27 +36,34 @@
}
function handleFilter(e) {
filter = e.detail
shownNotes = shownNotes.filter(note => {
return note.tags.includes(e.detail)
return note.tags.includes(filter)
})
}
function handleClearDone(e) {
if (clearConfirm === false) {
clearConfirm = true
} else {
clearConfirm = false
notes = notes.filter(note => !note.done)
shownNotes = notes
storage.saveNotes(notes)
}
notes = notes.filter(note => !note.done)
shownNotes = notes
storage.saveNotes(notes)
}
function handleClearFilter(e) {
filter = null
shownNotes = notes
}
function handleToggleDarkMode(e) {
console.log("Dark Mode: " + !darkMode)
theme = theme === "dark" ? "" : "dark"
storage.saveTheme(theme)
}
</script>
<svelte:head>
<title>Notes</title>
</svelte:head>
<main>
<MainInput on:added={handleNewNote} />
@ -56,11 +73,13 @@
{/each}
</section>
<footer>
<button on:click={handleClearFilter}>Clear filter</button>
<div class="flex-1" />
<button on:click={handleClearDone} class:confirm={clearConfirm}>Clear finished notes</button>
</footer>
<Actions
filter={filter}
hasFinishedNotes={hasFinishedNotes}
darkMode={darkMode}
on:clearDone={handleClearDone}
on:clearFilter={handleClearFilter}
on:toggleDarkMode={handleToggleDarkMode} />
</main>
@ -81,10 +100,24 @@
--gray-900: #0F172A;
}
:global(.dark) {
--gray-50: #0F172A;
--gray-100: #1E293B;
--gray-200: #334155;
--gray-300: #475569;
--gray-400: #64748B;
--gray-500: #94A3B8;
--gray-600: #CBD5E1;
--gray-700: #E2E8F0;
--gray-800: #F1F5F9;
--gray-900: #F8FAFC;
}
:global(body) {
padding: 0;
margin: 0;
background: var(--gray-100);
transition: 0.1s ease-in all;
}
main {
@ -93,33 +126,7 @@
margin: 0 auto;
}
footer {
display: flex;
}
.notes {
margin: 0.5rem 0;
}
.flex-1 {
display: flex;
flex: 1 1 0;
}
button {
background: var(--gray-200);
padding: 0.5rem;
border: 1px solid var(--gray-300);
transition: 0.1s ease-in all;
}
button:hover {
background: var(--gray-300);
color: var(--gray-700);
border: 1px solid var(--gray-400);
}
button.confirm {
color: red;
}
</style>

110
src/lib/Actions.svelte Normal file
View File

@ -0,0 +1,110 @@
<script>
import { createEventDispatcher } from 'svelte'
const dispatch = createEventDispatcher()
export let filter = null
export let hasFinishedNotes = false
export let darkMode = false
let clearConfirmed = false
$: filterText = filter ? `Clear '${filter}' filter` : "Clear filter"
function confirmClear(e) {
if (!clearConfirmed) {
clearConfirmed = true
} else {
clearConfirmed = false
dispatch('clearDone', null)
}
}
function clearFilter(e) {
dispatch('clearFilter', null)
}
function toggleDarkMode() {
dispatch('toggleDarkMode', null)
}
</script>
<aside class="flex gap">
<button
on:click={clearFilter}
disabled={filter === null}>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-funnel" viewBox="0 0 16 16">
<path d="M1.5 1.5A.5.5 0 0 1 2 1h12a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-.128.334L10 8.692V13.5a.5.5 0 0 1-.342.474l-3 1A.5.5 0 0 1 6 14.5V8.692L1.628 3.834A.5.5 0 0 1 1.5 3.5v-2zm1 .5v1.308l4.372 4.858A.5.5 0 0 1 7 8.5v5.306l2-.666V8.5a.5.5 0 0 1 .128-.334L13.5 3.308V2h-11z"/>
</svg>
{filterText}
</button>
<div class="flex-1" />
<button
on:click={confirmClear}
class:confirm={clearConfirmed}
disabled={hasFinishedNotes}>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-archive" viewBox="0 0 16 16">
<path d="M0 2a1 1 0 0 1 1-1h14a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1v7.5a2.5 2.5 0 0 1-2.5 2.5h-9A2.5 2.5 0 0 1 1 12.5V5a1 1 0 0 1-1-1V2zm2 3v7.5A1.5 1.5 0 0 0 3.5 14h9a1.5 1.5 0 0 0 1.5-1.5V5H2zm13-3H1v2h14V2zM5 7.5a.5.5 0 0 1 .5-.5h5a.5.5 0 0 1 0 1h-5a.5.5 0 0 1-.5-.5z"/>
</svg>
Clear finished notes
</button>
<button on:click={toggleDarkMode}>
{#if darkMode}
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-moon" viewBox="0 0 16 16">
<path d="M6 .278a.768.768 0 0 1 .08.858 7.208 7.208 0 0 0-.878 3.46c0 4.021 3.278 7.277 7.318 7.277.527 0 1.04-.055 1.533-.16a.787.787 0 0 1 .81.316.733.733 0 0 1-.031.893A8.349 8.349 0 0 1 8.344 16C3.734 16 0 12.286 0 7.71 0 4.266 2.114 1.312 5.124.06A.752.752 0 0 1 6 .278zM4.858 1.311A7.269 7.269 0 0 0 1.025 7.71c0 4.02 3.279 7.276 7.319 7.276a7.316 7.316 0 0 0 5.205-2.162c-.337.042-.68.063-1.029.063-4.61 0-8.343-3.714-8.343-8.29 0-1.167.242-2.278.681-3.286z"/>
</svg>
{:else}
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-brightness-high" viewBox="0 0 16 16">
<path d="M8 11a3 3 0 1 1 0-6 3 3 0 0 1 0 6zm0 1a4 4 0 1 0 0-8 4 4 0 0 0 0 8zM8 0a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-1 0v-2A.5.5 0 0 1 8 0zm0 13a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-1 0v-2A.5.5 0 0 1 8 13zm8-5a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1 0-1h2a.5.5 0 0 1 .5.5zM3 8a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1 0-1h2A.5.5 0 0 1 3 8zm10.657-5.657a.5.5 0 0 1 0 .707l-1.414 1.415a.5.5 0 1 1-.707-.708l1.414-1.414a.5.5 0 0 1 .707 0zm-9.193 9.193a.5.5 0 0 1 0 .707L3.05 13.657a.5.5 0 0 1-.707-.707l1.414-1.414a.5.5 0 0 1 .707 0zm9.193 2.121a.5.5 0 0 1-.707 0l-1.414-1.414a.5.5 0 0 1 .707-.707l1.414 1.414a.5.5 0 0 1 0 .707zM4.464 4.465a.5.5 0 0 1-.707 0L2.343 3.05a.5.5 0 1 1 .707-.707l1.414 1.414a.5.5 0 0 1 0 .708z"/>
</svg>
{/if}
</button>
</aside>
<style>
aside {
display: flex;
}
button {
color: var(--gray-800);
background: var(--gray-200);
padding: 0.5rem;
border: 1px solid var(--gray-300);
border-radius: 0.15rem;
font-size: 0.75rem;
}
button:disabled {
color: var(--gray-400);
}
button:hover:not(:disabled) {
background: var(--gray-300);
color: var(--gray-700);
border: 1px solid var(--gray-400);
cursor: pointer;
}
button.confirm, button.confirm:hover {
color: red;
}
button svg {
display: inline-block;
vertical-align: -0.25em;
fill: currentcolor;
margin-right: 0.125em;
}
.flex {
display: flex;
}
.flex-1 {
display: flex;
flex: 1 1 0;
}
.gap {
gap: 0.5rem;
}
</style>

View File

@ -11,7 +11,7 @@
}
</script>
<input type="text" on:keyup={handleKeyup} placeholder="Add a new note, tag with #foo and #bar">
<input type="text" on:keyup={handleKeyup} placeholder="Add a new note, tag with #foo and #bar and press ENTER">
<style>
input {
@ -20,5 +20,8 @@
box-sizing: border-box;
border: 1px solid var(--gray-400);
border-radius: 0.15rem;
font-size: 1rem;
color: var(--gray-800);
background: var(--gray-50);
}
</style>

View File

@ -34,9 +34,10 @@
display: flex;
gap: 0.5rem;
color: var(--gray-800);
padding: 0.5rem;
background: white;
border: 1px solid var(--gray-400);
background: var(--gray-100);
border: 1px solid var(--gray-300);
border-radius: 0.15rem;
margin-bottom: 0.25rem;
@ -59,5 +60,7 @@
.title {
flex: 1;
cursor: pointer;
font-size: 1rem;
}
</style>

View File

@ -3,6 +3,14 @@ export default class Storage {
this.prefix = "notesapp"
}
getTheme() {
return localStorage.getItem(`${this.prefix}-theme`) || ""
}
saveTheme(theme) {
localStorage.setItem(`${this.prefix}-theme`, theme)
}
getNotes() {
const notesString = localStorage.getItem(`${this.prefix}-notes`)
if (notesString) {